题目大意:在一个国际象棋盘上放置皇后,使得目标全部被占领,求最少的皇后个数。
题目分析:迭代加深搜索,否则超时。
小技巧:用vis[0][r]、vis[1][c]、vis[2][r+c]、vis[c-r+N]分别标志(r,c)位置相对应的行、列、主、副对角线有没有被占领(详见《入门经典(第2版)》P193),其中N表示任意一个比行数和列数都大(大于等于)的数。
代码如下:
# include<iostream> # include<cstdio> # include<cstring> # include<algorithm> using namespace std; char p[13][13]; int vis[4][30],n,m,ans; bool dfs(int cur,int maxd) { if(cur==maxd){ for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) if(p[i][j]=='X'&&!vis[0][i]&&!vis[1][j]&&!vis[2][i+j]&&!vis[3][j-i+11]) return false; return true; } for(int i=cur+1;i<=n;++i){ for(int j=1;j<=m;++j){ if(!vis[0][i]||!vis[1][j]||!vis[2][i+j]||!vis[3][j-i+11]){ int a=vis[0][i],b=vis[1][j],c=vis[2][i+j],d=vis[3][j-i+11]; vis[0][i]=vis[1][j]=vis[2][i+j]=vis[3][j-i+11]=1; if(dfs(cur+1,maxd)) return true; vis[0][i]=a,vis[1][j]=b,vis[2][i+j]=c,vis[3][j-i+11]=d; } } } return false; } int main() { int cas=0; while(scanf("%d",&n)&&n) { scanf("%d",&m); for(int i=1;i<=n;++i) scanf("%s",p[i]+1); int ans; for(ans=1;;++ans){ memset(vis,0,sizeof(vis)); if(dfs(0,ans)) break; } printf("Case %d: %d ",++cas,ans); } return 0; }