HDU4012 Paint on a Wall(BFS)

来源:互联网 发布:ubuntu 开启ssh服务 编辑:程序博客网 时间:2024/05/01 08:49

一开始确实没看出来什么玄机。然后搜了搜题解。由于最多只有16个格子,用二进制的状态压缩来表示,状态为1的位表示该位已经涂上了正确的颜色。
从第一行的i号节点开始向两边涂色的时候注意:如果刷到的这个节点已经是它本身的正确的颜色,那么我们就不刷了。否则这样又刷回了错误的颜色,就不是最优解了。然后把每扩展一个格子的状态全部压入队列,也就是代码中的tmp。
此外,同时刷两行颜色的时候只用考虑第一行就行了。

#include<cstdio>#include<cstring>#include<queue>using namespace std;struct Node{    int s,stp;    Node(){}    Node(int a,int b)    {s = a; stp = b;}}st;char str[20];bool vis[1<<16];int n,cas;void bfs(){    int ed = (1<<(2*n))-1;    memset(vis,0,sizeof vis);    queue<Node> Q;    Q.push(st);    while(!Q.empty())    {        Node u = Q.front(),v;        Q.pop();        if(u.s == ed)        {            printf("Case #%d: %d\n",cas,u.stp);            return;        }        for(int i = 0; i < 2*n; i++)        {            if((1<<i)&u.s) continue;            int tmp = 0;            for(int j = i; j < (i/n+1)*n; j++)//右刷,这种写法把两行的情况都考虑了,很巧妙            {                if((1<<j)&u.s) break;                if(str[i] == str[j]) tmp |= (1<<j);            }            for(int j = i-1; j >= (i/n)*n; j--)//左刷            {                if((1<<j)&u.s) break;                if(str[i] == str[j]) tmp |= (1<<j);            }            for(int j = tmp; j; j = (j-1)&tmp)//神奇的判断子集的方法,可以动手实验一下            {                if(vis[u.s|j]) continue;                vis[u.s|j] = 1;                Q.push(Node(u.s|j,u.stp+1));            }            if(i >= n) break;            if((1<<(i+n))&u.s) continue;            tmp = 0;            for(int j = i; j < n; j++)            {                if(((1<<j)&u.s)||((1<<(j+n))&u.s)) break;                if(str[i] == str[j]) tmp |= 1<<j;                if(str[i] == str[j+n]) tmp |= 1<<(j+n);            }            for(int j = i-1; j >= 0; j--)            {                if(((1<<j)&u.s)||((1<<(j+n))&u.s)) break;                if(str[i] == str[j]) tmp |= 1<<j;                if(str[i] == str[j+n]) tmp |= 1<<(j+n);            }            for(int j = tmp; j; j = (j-1)&tmp)            {                if(vis[u.s|j]) continue;                vis[u.s|j] = 1;                Q.push(Node(u.s|j,u.stp+1));            }        }    }}int main(){    int T;    scanf("%d",&T);    while(T--)    {        cas++;        scanf("%d",&n);        scanf("%s",str);        scanf("%s",str+n);        st.s = st.stp = 0;        bfs();    }}
0 0