poj_1735_Flip Game

一道需要活躍思維的搜索題,當然,對於2^16 的複雜度也可以枚舉來做.


題目大意: http://poj.grids.cn/practice/1753/

給一個4*4的棋盤,上面有黑子 (用字符'b'表示) 和白子 (用字符'w'表示) .可以選擇棋子翻轉,每翻轉一個棋子,其周圍四個棋子也會被翻轉(邊角情況正常處理),問最少翻轉多少次可以讓棋盤全黑或全白.

解題思路:

一看只有16個格子,首先想到了枚舉~:

for(int i=0;i<1;++i)

.

.

.

16層......後來一想這麼寫多丟人......所以還是搜索吧,bfs和dfs基本都沒有問題,因爲求最少步數,所以還是bfs比較適合.

把棋盤看做簡單的0-1矩陣,對每一個位置取反時也會對周圍4個位置取反,對一個數取反可以寫做: n=n^1; .那麼從什麼狀態開始搜素呢?~

將0-1矩陣合併,看成一個二進制數,那麼他的範圍僅僅爲 0-0xffff 也就是一共僅有 0xfff 種狀態.對每一位翻轉,可以求出其狀態轉移方程:

   當前狀態a ^ 轉移狀態i (i爲翻轉的位置),a==0 時結束,每個位置會有其單獨的翻轉狀態.比如 0,0 位:

    1100  
    1000  
    0000  
    0000    周圍四個位置取反.  

接下來就是麼每一位的轉移狀態i的處理. 將矩陣每一位編號.

    F E D C  
    B A 9 8  
    7 6 5 4  
    3 2 1 0  

那麼,其上下左右就爲: 上: -4 下:+4 左:-1 右: +1 求轉移狀態的源碼就爲:


    void build() {  
        memset(no,0,sizeof(no));  
        int num=1;  
        for(int i=N;i>0;--i) {  
            for(int j=1;j<=4;++j) {  
                int tx=i*4-j;  
                no[num]=1<<(tx);  
                for(int k=0;k<4;++k) {  
                    int x=tx+dbit[k];  
                    if(x<0||x>15)  
                        continue;  
                    if((tx+4)%4==0&&(x+4)%4==3) {  
                        continue;  
                    }  
                    if((tx+4)%4==3&&(x+4)%4==0) {  
                        continue;  
                    }  
                    no[num]=no[num]+(1<<x);  
                }       
                num++;  
            }  
        }  
    }  

求出轉移狀態後,就以每一個點爲起點bfs 即可:

    #include <myhead.h>  
    const int N=4;  
    const int s=0xffff;  
    const int t=0;  
    const int dbit[]={-4,1,+4,-1};  
    struct Node {  
        int m,num;  
        int i;  
    };  
    bool _hash[100000];  
    char a[N+1][N+1];  
    int no[20];  
    Node node;  
      
    void build() {  
        memset(no,0,sizeof(no));  
        int num=1;  
        for(int i=N;i>0;--i) {  
            for(int j=1;j<=4;++j) {  
                int tx=i*4-j;  
                no[num]=1<<(tx);  
                for(int k=0;k<4;++k) {  
                    int x=tx+dbit[k];  
                    if(x<0||x>15)  
                        continue;  
                    if((tx+4)%4==0&&(x+4)%4==3) {  
                        continue;  
                    }  
                    if((tx+4)%4==3&&(x+4)%4==0) {  
                        continue;  
                    }  
                    no[num]=no[num]+(1<<x);  
                }       
                num++;  
            }  
        }  
    }  
      
    bool init() {  
        for(int i=0;i<N;++i) {  
            if(scanf("%s",a[i])==EOF) {  
                return false;  
            }  
        }  
        memset(_hash,0,sizeof(_hash));  
        node.i=node.m=node.num=0;  
        int m=0;  
        for(int i=N-1;i>=0;--i) {  
            for(int j=N-1;j>=0;--j) {  
                if(a[i][j]=='b') {  
                    node.m=node.m+(1<<m);  
                }  
                m=m+1;  
            }  
        }  
        return true;  
    }  
      
    void bfs() {  
        queue<Node> q;  
        q.push(node);  
        while(!q.empty()) {  
            Node tmp=q.front();  
            q.pop();  
            if(tmp.m==s||tmp.m==0) {  
                printf("%d\n",tmp.num);  
                return ;  
            }  
            node.num=tmp.num+1;  
            for(int i=1;i<=16;++i) {  
                if(tmp.i!=i) {  
                    node.i=i;  
                    node.m=(tmp.m^no[i]);  
                    if(!_hash[node.m]) {  
                        _hash[node.m]=true;  
                        q.push(node);  
                    }  
                }  
            }  
        }  
        printf("Impossible");  
    }  
      
    int main()  
    {  
        build();  
        init();  
        bfs();  
        return 0;  
    }  


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章