LightOJ 1061 N Queen Again(记忆化搜索)

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1061

题意:给定8*8的棋盘上8个皇后。挪动最少的步数使得不互相攻击?

思路:首先预处理求出所有的合法放法(就是这里一开始想了好久没想出来)。然后对于每个测试数据,枚举每一种合法放法。。。枚举的时候记忆化搜索和直接BFS都行,前一种快点。。

 

View Code
  1 //记忆化搜索

  2 #include <iostream>

  3 #include <cstdio>

  4 #include <cstring>

  5 #define min(x,y) ((x)<(y)?(x):(y))

  6 using namespace std;

  7  

  8 struct node

  9 {

 10     int x[10],y[10];

 11 };

 12  

 13 node ans[1000],p;

 14 int sum;

 15 int C,num=0;

 16 char s[10][10];

 17  

 18 int abs(int x)

 19 {

 20     return x>0?x:-x;

 21 }

 22  

 23 inline int OK(int x,int y,node a,int n)

 24 {

 25     int i;

 26     for(i=1;i<=n;i++) if(a.y[i]==y||abs(a.x[i]-x)==abs(a.y[i]-y))

 27        return 0;

 28     return 1;

 29 }

 30  

 31 void DFS(int dep,node &a)

 32 {

 33     if(dep==9)

 34     {

 35         ans[++sum]=a;

 36         return;

 37     }

 38     int i;

 39     for(i=1;i<=8;i++) if(OK(dep,i,a,dep-1))

 40     {

 41         a.x[dep]=dep;

 42         a.y[dep]=i;

 43         DFS(dep+1,a);

 44     }

 45 }

 46  

 47 void init()

 48 {

 49     sum=0;

 50     node a;

 51     DFS(1,a);

 52 }

 53  

 54 const int INF=1000000000;

 55 int f[10][300];

 56  

 57 inline int get(node a,int t1,node b,int t2)

 58 {

 59     int x1=a.x[t1],y1=a.y[t1];

 60     int x2=b.x[t2],y2=b.y[t2];

 61     if(x1==x2&&y1==y2) return 0;

 62     if(x1==x2||y1==y2||abs(x1-x2)==abs(y1-y2)) return 1;

 63     return 2;

 64 }

 65  

 66 int DFS1(int u,int st,node a)

 67 {

 68     if(u==8) return 0;

 69     if(f[u][st]!=-1) return f[u][st];

 70     int i,t=INF;

 71     for(i=0;i<8;i++) if(0==(st&(1<<i)))

 72         t=min(t,get(p,u+1,a,i+1)+DFS1(u+1,st|(1<<i),a));

 73     return f[u][st]=t;

 74 }

 75  

 76 int deal()

 77 {

 78     int temp=INF,i;

 79     for(i=1;i<=sum;i++)

 80     {

 81         memset(f,-1,sizeof(f));

 82         temp=min(temp,DFS1(0,0,ans[i]));

 83     }

 84     return temp;

 85 }

 86  

 87 int main()

 88 {

 89     init();

 90     for(scanf("%d",&C);C--;)

 91     {

 92         int i,j,k=0;

 93         for(i=1;i<=8;i++)

 94         {

 95             scanf("%s",s[i]+1);

 96             for(j=1;j<=8;j++) if(s[i][j]=='q')

 97             {

 98                 p.x[++k]=i;

 99                 p.y[k]=j;

100             }

101         }

102         printf("Case %d: %d\n",++num,deal());

103     }

104     return 0;

105 }

106 

107 //直接BFS

108 #include <iostream>

109 #include <cstdio>

110 #include <cstring>

111 #include <queue>

112 #define min(x,y) ((x)<(y)?(x):(y))

113 using namespace std;

114 

115 struct node

116 {

117     int x[10],y[10];

118 };

119 

120 node ans[1000],p;

121 int sum;

122 int C,num=0;

123 char s[10][10];

124 

125 int abs(int x)

126 {

127     return x>0?x:-x;

128 }

129 

130 inline int OK(int x,int y,node a,int n)

131 {

132     int i;

133     for(i=1;i<=n;i++) if(a.y[i]==y||abs(a.x[i]-x)==abs(a.y[i]-y))

134         return 0;

135     return 1;

136 }

137 

138 void DFS(int dep,node &a)

139 {

140     if(dep==9)

141     {

142         ans[++sum]=a;

143         return;

144     }

145     int i;

146     for(i=1;i<=8;i++) if(OK(dep,i,a,dep-1))

147     {

148         a.x[dep]=dep;

149         a.y[dep]=i;

150         DFS(dep+1,a);

151     }

152 }

153 

154 void init()

155 {

156     sum=0;

157     node a;

158     DFS(1,a);

159 }

160 

161 

162 

163 inline int get(node a,int t1,node b,int t2)

164 {

165     int x1=a.x[t1],y1=a.y[t1];

166     int x2=b.x[t2],y2=b.y[t2];

167     if(x1==x2&&y1==y2) return 0;

168     if(x1==x2||y1==y2||abs(x1-x2)==abs(y1-y2)) return 1;

169     return 2;

170 }

171 

172 const int INF=1000000000;

173 int f[66000],visit[66000];

174 

175 int cal(node a,node b)

176 {

177     int k,aa,bb,k0,aa0,bb0,i,j,cost;

178     queue<int> Q;

179     memset(f,-1,sizeof(f));

180     memset(visit,0,sizeof(visit));

181     f[255]=0;

182     visit[255]=1;

183     Q.push(255);

184     while(!Q.empty())

185     {

186         k=Q.front();

187         Q.pop();

188         visit[k]=0;

189         aa=k>>8;

190         bb=k&255;

191         for(i=0;i<8;i++) if(bb&(1<<i))

192         {

193             for(j=0;j<8;j++) if(0==(aa&(1<<j)))

194             {

195                 aa0=aa^(1<<j);

196                 bb0=bb^(1<<i);

197                 k0=(aa0<<8)+bb0;

198                 cost=get(b,i+1,a,j+1);

199                 if(f[k0]==-1||f[k0]>f[k]+cost)

200                 {

201                     f[k0]=f[k]+cost;

202                     if(!visit[k0])

203                     {

204                         Q.push(k0);

205                         visit[k0]=1;

206                     }

207                 }

208             }

209             break;

210         }

211     }

212     return f[255<<8];

213 }

214 

215 int deal()

216 {

217     int temp=INF,i;

218     for(i=1;i<=sum;i++)

219     {

220         memset(f,-1,sizeof(f));

221         temp=min(temp,cal(ans[i],p));

222     }

223     return temp;

224 }

225 

226 int main()

227 {

228     init();

229     for(scanf("%d",&C);C--;)

230     {

231         int i,j,k=0;

232         for(i=1;i<=8;i++)

233         {

234             scanf("%s",s[i]+1);

235             for(j=1;j<=8;j++) if(s[i][j]=='q')

236             {

237                 p.x[++k]=i;

238                 p.y[k]=j;

239             }

240         }

241         printf("Case %d: %d\n",++num,deal());

242     }

243     return 0;

244 }

 

 

 

你可能感兴趣的:(搜索)