noi1816 画家问题(技巧搜索Dfs)

/*
Problem 画家问题
假设一个ans数组存的是对每一个点的操作 0表示不图 1表示图
那么 对于原图 g 操作第三行时对第一行没有影响 同样往下类似的
所以 假设我们知道了ans的第一行就是最后答案的第一行 那么对于ans的第二行 就必须是的第一行全变成黄色
以此类推 最后检验第n行 是不是全部黄色就好了
所以只需要枚举第一行的所有情况 共2的n次方种情况 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define inff 0x7fffffff
using namespace std;
int n,ans[20][20],g[20][20],tmp[20][20],anss,minn=inff,tot;
char s;
void Printf()//计数 染了几个 
{
    anss=0;
    for(int i=1;i<=n;i++)
      for(int j=1;j<=n;j++)
        if(ans[i][j]==1)anss++;
    minn=min(minn,anss);
}
void Pai()//根据ans的第一行 逐行染色 
{
    int i,j,f=0;
    memset(tmp,0,sizeof(tmp));
    for(i=1;i<=n;i++)
      for(j=1;j<=n;j++)
        tmp[i][j]=g[i][j];
    for(i=1;i<=n;i++)
      {
          if(ans[1][i]==1)
            {
              tmp[1][i]=!tmp[1][i];
              tmp[1][i+1]=!tmp[1][i+1];
              tmp[1][i-1]=!tmp[1][i-1];
              tmp[2][i]=!tmp[2][i];
          }
      }
    for(i=2;i<=n;i++)
      for(j=1;j<=n;j++)
        if(tmp[i-1][j]==1)
          {
            tmp[i-1][j]=0;
              ans[i][j]=1;
              tmp[i][j]=!tmp[i][j];
              tmp[i][j+1]=!tmp[i][j+1];
              tmp[i][j-1]=!tmp[i][j-1];
              tmp[i+1][j]=!tmp[i+1][j];
          }
    for(i=1;i<=n;i++)//最后检验最后一行是不是恰好全为黄色 
      if(tmp[n][i]==1)f=1;
    if(f==0)Printf();
}
void Dfs(int t)//枚举ans的第一行的所有情况 
{
    if(t>n)
      {
          for(int i=2;i<=n;i++)
            for(int j=1;j<=n;j++)
              ans[i][j]=0;
          Pai();
        return;
      }
    ans[1][t]=1;Dfs(t+1);
    ans[1][t]=0;Dfs(t+1);
}
int main()
{
    int i,j;
    cin>>n;
    for(i=1;i<=n;i++)
      for(j=1;j<=n;j++)
        {
          cin>>s;
          if(s=='w')g[i][j]=1;
          else g[i][j]=0;
        }
    Dfs(1);
    if(minn<0x7fffffff)cout<<minn;
    else cout<<"inf";
}

 

posted @ 2016-04-18 19:51  一入OI深似海  阅读(546)  评论(0编辑  收藏  举报