【题意】这两天和n皇后问题结缘了-><-,这是这两天做的第二个n皇后问题,跟紧学弟学妹的步伐,是时候提高搜索的能力了!闲话少说,直接上题意了。这道题说的是给了一个8*8棋盘上的皇后的状态。问你这个状态到一个合法的状态需要走的最小步数!
【分析】一种可行的方法是先把8皇后问题所有可能的合法状态初始化出来,然后对于每个状态计算这个状态到棋盘的状态所需要的步数的最小值。当然我也是这样做的。
【AC代码】
#include <stdio.h> #include <ctype.h> #include <assert.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <algorithm> using namespace std; const int inf = 1<<30; const int maxn = 1010; struct node{ //结构体保存皇后的位置的状态。 int x[10],y[10]; }; node ans[maxn];//用来存储合法的皇后问题 node init;//初始状态 int f[10][300];//哪一行,哪个状态?状态标记,记忆化搜索不可或缺 int sum,k; char s[10][10];//初始棋盘状态 inline int ok(int x,int y,node a,int n)//判断当前坐标和以前的皇后的位置是否冲突 { for(int i=1;i<=n;i++) { if(a.y[i]==y||abs(a.x[i]-x)==abs(a.y[i]-y)) return 0; } return 1; } void DFS(int dep,node &a)//普通回溯,处理处所有的合法的状态 { if(dep==9) { ans[++sum] = a; return ; } for(int i=1; i<=8; i++) { if(ok(dep,i,a,dep-1)) { a.x[dep] = dep; a.y[dep] = i; DFS(dep+1,a); } } } void Init() { sum = 0; node a; DFS(1,a); } inline int walk(node a,int t1,node b,int t2)//计算棋盘的两个点相互到达需要的步数 { int x1 = a.x[t1],x2 = b.x[t2]; int y1 = a.y[t1],y2 = b.y[t2]; if(x1==x2&&y1==y2) return 0; if(x1==x2||y1==y2||abs(x1-x2)==abs(y1-y2)) return 1; else return 2; } int DFS1(int u,int st,node a) { if(u==8) return 0; if(f[u][st]!=-1) return f[u][st]; int T = inf; for(int i=0;i<8;i++)//从上至下枚举,维护所有合法状态和给定状态的转移步数的最小值 { if(st&(1<<i)) continue; T = min(T,walk(init,u+1,a,i+1)+DFS1(u+1,st^(1<<i),a)); } return f[u][st] = T; } int work() { int temp = inf; for(int i=1; i<=sum; i++) { memset(f,-1,sizeof(f)); temp = min(temp,DFS1(0,0,ans[i])); } return temp; } int main() { Init(); int T,cas=1; scanf("%d",&T); while(T--) { k = 0; for(int i=1; i<=8; i++) { scanf("%s",s[i]+1); for(int j=1; j<=8; j++) { if(s[i][j]=='q') { init.x[++k] = i; init.y[k] = j; } } } int ans = work(); printf("Case %d: %d\n",cas++,ans); } return 0; }