ページ 11

bit演算について

Posted: 2015年5月12日(火) 12:20
by きょう
今、bit演算で困っていることがあります。
今の時点で分かっている内容は
1<<2・・・1を二進数に表して、左に2ビット分シフトする。
if((4>>1&1)==1)・・・4を二進数100にして、右にビットシフトさせ、10となり、その一ビット目が1ならtrueを返す。
です。
問題は、これをどう解く方法として使うかです。
たとえば、http://judge.u-aizu.ac.jp/onlinejudge/d ... sp?id=0595(AOJ)の問題があって、
解答例として、参考にしていますコードは次の通りです。

コード:

int dp[1001][8];
int n;
string moji;
char num[1001];
int main()
{
    cin>>n;
    cin>>moji;
    for(int i=0;i<n;i++)
    {
        if(moji[i]=='J')
        {
            num[i]=0;
        }
        else if(moji[i]=='O')
        {
            num[i]=1;
        }
        else
        {
            num[i]=2;
        }
    }
    dp[0][1]=1;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<8;j++)
        {
            if((j>>num[i-1]&1)==0)・・・①
            continue;
            for(int k=1;k<8;k++)
            {
                if((j&k)==0)・・・②
                {
                    continue;
                }
                dp[i][j]+=dp[i-1][k];
                dp[i][j]%=10007;
            }
        }
    }
    int ans=0;
    for(int i=0;i<8;i++)
    {
        ans=(ans+dp[n][i])%10007;
    }
    cout<<ans<<endl;
    return 0;
} 
 
わからないところは、①と②です。
②は、jとkが両方含まれていなかったらfalseを返すのまではわかりました。
しかし、①はどういうことをしているのか全く分かりません。jをnum[i-1]ビット分右にずらし、1ビット目を見ることは、どういうことがわかるのでしょうか?
漠然とした質問すみません。
よろしくお願いしたします。

Re: bit演算について

Posted: 2015年5月13日(水) 05:41
by トントン
競技プログラミングはあまり詳しくないのですが
動的計画法ですね。

考え方として
num[2] = I
num[1] = O
num[0] = J
とすると
IOJ | 1→参加 0→不参加
---
000 |1パターン目
001 |2パターン目
010 |3パターン目
011 |4パターン目
100 |5パターン目
101 |6パターン目
110 |7パターン目
111 |8パターン目

前提として、dp[日数][パターン]
→ 初日は必ずJさんが必要なので
24行目でdp[1日目][2パターン目] = 1パターン確定

・・・①の考え方は
責任者が参加しているか判断しています。
つまり「入力例 1」を参考にすると
初日は必ずOさんが参加する必要があります。
なので、Oさんが参加しているパターン
上記テーブルの3パターン目、4パターン目、7パターン目、8パターン目
の際に判定を継続するようになっています。

・・・②の考え方は
参加者が鍵を持っているか判定しています。
今回の参加者のうち、前回参加している人がいれば鍵が渡っているので0にならないので
処理が継続されるようになっています。
上記に当てはまらない場合、鍵を誰ももっていないので処理が飛ぶようになっています。

----
ちょうど早朝に書いているので
殴り書き+考えが間違っているかもしれません。
そこらへんは、きっと得意な人が訂正してくれると思います。

ヒントになれば幸いです。