POJ 1753 位运算+BFS

来源:互联网 发布:巴厘岛旅游攻略知乎 编辑:程序博客网 时间:2024/05/16 04:26

利用位运算来优化

     因为棋子不是白就是黑,所以可以用0和1来表示。

     然后为每一个棋子编号,并计算出该棋子若翻转会影响到的棋子的位置,可以把它们都看成是二进制的。

    例如 棋子位置是 第二行第二列                     则翻转该棋子会影响到的棋子位置是

                0 0 0 0                      0 1 0 0

                0 1 0 0                      1 0 1 0

                0 0 0 0                      0 1 0 0

                0 0 0 0                      0 0 0 0

    二进制表示        0000 0100 0000 0000              0100 1010 0100 0000

        

    当计算最小值时可以预处理一下,即计算出由全白到该方案最少需要步数以及全黑到该方案需要的最少步数。

    然后每一种方案都可以通过枚举 dp[j] = min(dp[j], dp[i]+1)来得到,dp[i]表示左上的状态,dp[j]表示右上的状态。

    j = 影响的棋子位置^i

    

    再优化之:其实,所以用dp[(1<<16-1)^i]得到的状态j即是状态i到全黑的最少步数, 这样就可以减少一个数组的开销了。


#include <iostream>using namespace std;const int INF = 0x7fffffff;const int MAX = 1<<16;int dir[5][2]={{0,0}, {0,-1}, {0,1}, {-1,0}, {1,0}};int dp[MAX];int effect[16], tot=0;bool check(int x, int y){    return (x<4 && x>=0 && y<4 &&y>=0);}void init(){    int temp;    for(int i=0;i<MAX;i++) dp[i]=INF;    for(int i=0;i<4;i++)        for(int j=0;j<4;j++)        {            temp=0;            for(int k=0;k<5;k++)            {                int x, y;                x=i+dir[k][0];  y=j+dir[k][1];                if(check(x,y))  temp|=(1<<(4*x+y));            }            effect[tot++]=temp;        }}void BFS(){    int j;    dp[0]=0;    for(int i=0;i<MAX;i++)    {        if(dp[i]==INF) continue;        for(int k=0;k<tot;k++)        {            j=i^effect[k];            dp[j]=min(dp[i]+1,dp[j]);        }    }}int main(){    char ch[10];    int num;    init();    BFS();    num=0;    for(int i=0;i<4;i++)    {        cin>>ch;        for(int j=0;j<4;j++)        {            if(ch[j]=='b') num|=(1<<(4*i+j));        }    }    if(dp[num]==INF && dp[num^(MAX-1)]==INF) cout<<"Impossible\n";    else cout<<min(dp[num],dp[num^(MAX-1)])<<endl;    return 0;}



原创粉丝点击