POJ 1681 Painter's Problem(开关问题)

来源:互联网 发布:轰天雷软件下载 编辑:程序博客网 时间:2024/06/06 03:16

开关问题的解法:把第一行的数开或关有2^n次方种可能00000-11111.遍历这么多种可能,给第一行赋值,第二行考虑让自己能影响到的第一行的数成立,第三行考虑让自己能影响到的第二行的数成立……最后判断一下是否所有的数都能成立。复杂度为(n*n*2^n)所以n必须是一个小的值

#include "cstdio"#include "iostream"#include "cstring"using namespace std;bool wall[18][18];bool paint[18][18];int count1,n;bool allyellow(){    count1=0;    for(int i=1; i<=n; i++)        {for(int j=1; j<=n; j++)        {            if(wall[i][j]^paint[i][j]^paint[i][j-1]^paint[i][j+1]^paint[i-1][j]^paint[i+1][j])                return false;              if(paint[i][j]==1)count1++;        }        }    return true;}int main(){    int t;    char c;    scanf("%d",&t);    while(t--)    {        memset(wall,0,sizeof(wall));        scanf("%d%*c",&n);        for(int i=1; i<=n; i++)        {            for(int j=1; j<=n; j++)            {                scanf("%c",&c);                if(c=='w')wall[i][j]=1;            }            getchar();        }        int maxn=1<<n;        int min1=1000;        for(int i=0; i<maxn; i++)        {            memset(paint,0,sizeof(paint));            int tmp=i;            for(int j=1; j<=n; j++)            {                paint[1][j]=tmp&1;                tmp/=2;            }            for(int k=2; k<=n; k++)            {                for(int p=1; p<=n; p++)                {                     if(wall[k-1][p]^paint[k-1][p]^paint[k-1][p-1]^paint[k-1][p+1]^paint[k-2][p])                        paint[k][p]=true;                }            }            if(allyellow()==true)            {                min1=min(min1,count1);            }        }        if(min1==1000)printf("inf\n");        else printf("%d\n",min1);    }    return 0;}


原创粉丝点击