poj1681 Painter's Problem

题目描述:

和那道关灯差不多,求最少涂几次。

题解:

高消,然后深搜枚举自由元更新答案。

貌似这道题没卡贪心但是其他题基本都卡了。

比如$Usaco09Nov$的$lights$

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 20;
int t,n,dx[]={-1,1,0,0},dy[]={0,0,1,-1};
char mp[N][N];
bool check(int x,int y)
{
    return x>=1&&x<=n&&y>=1&&y<=n;
}
int _id(int x,int y)
{
    return (x-1)*n+y;
}
int a[N*N][N*N],ans;
void gs()
{
    for(int l1=1;l1<=n*n;l1++)
    {
        int tmp = l1;
        while(tmp<=n*n&&!a[tmp][l1])tmp++;
        if(tmp>n*n)continue;
        if(tmp!=l1)
            for(int i=l1;i<=n*n+1;i++)swap(a[tmp][i],a[l1][i]);
        for(int i=1;i<=n*n;i++)if(a[i][l1]&&i!=l1)
            for(int j=l1;j<=n*n+1;j++)a[i][j]^=a[l1][j];
    }
}
void dfs(int dep,int now)
{
    if(now>=ans)return ;
    if(!dep){ans=now;return ;}
    if(a[dep][dep])
    {
        dfs(dep-1,now+a[dep][n*n+1]);
    }else
    {
        if(a[dep][n*n+1])return ;
        dfs(dep-1,now);
        for(int i=dep-1;i>=1;i--)if(a[i][dep])
            a[i][n*n+1]^=1;
        dfs(dep-1,now+1);
        for(int i=dep-1;i>=1;i--)if(a[i][dep])
            a[i][n*n+1]^=1;
    }
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        memset(a,0,sizeof(a));
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%s",mp[i]+1);
        for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)
        {
            int u = _id(i,j);
            a[u][u]=1;
            for(int k=0;k<4;k++)
            {
                int x = i+dx[k],y = j+dy[k];
                if(check(x,y))
                    a[u][_id(x,y)]=1;
            }
            a[u][n*n+1]=(mp[i][j]=='w');
        }
        gs();
        ans=0x3f3f3f3f;
        dfs(n*n,0);
        if(ans==0x3f3f3f3f)puts("inf");
        else printf("%d\n",ans);
    }
    return 0;
}

 

posted @ 2019-03-04 22:52  LiGuanlin  阅读(97)  评论(0编辑  收藏  举报