题目描述:
和那道关灯差不多,求最少涂几次。
题解:
高消,然后深搜枚举自由元更新答案。
貌似这道题没卡贪心但是其他题基本都卡了。
比如$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 ",ans); } return 0; }