Eight Queens UVa 750
当时就觉得回溯法学的不是很好,在处理dp多状态问题前,温习一遍回溯法:把待求解的问题分成不太多的步骤,每个步骤只有不太多的选择,就可以考虑回溯法。
普通八皇后思路:从64格子中选8个格子,枚举的话一共有C864=4.426X109解法,不爆才怪。
观察基本性质,每一行只能有一个皇后,所以最多只有8!种枚举可能。在实际操作的时候,状态树伸展肯定比这个值还要小,因为和之前的状态已经发生冲突,递归函数就不会再调用自身,而是返回上一层调用,这种现象被称为回溯(backtracking)。 回溯的关键在于回到上层调用时,要把改过去的状态改回来!否则原来状态被改变就不是原状态了。
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 int tot; 2 bool attacked[3][16];// 0 1 2分别表示是否被前面的皇后占据了列,左斜线,右斜线, 后面表示棋盘长度(8皇后有15斜) 3 4 void search(int a){ //逐行搜索 5 if(a==n){ 6 tot++; //递归边界,到了这里表示已经圆满完成 7 } 8 else{ 9 for(int i=0;i<n;i++){ //对于这一行,判断这一列能不能放 10 if(!attacked[0][i]&&!attacked[1][a+i]&&!attacked[2][n-a+i]){ 11 //尝试放置 12 // cell[a] = i; //记录这行放置的列,用于打印 13 attacked[0][i] = true; 14 attacked[1][a+i] = true; 15 attacked[2][n-a+i] = true; 16 search(a+1); 17 //调用完毕后一定要把状态改回来! 18 //也就是说改变的状态是给之后的子状态用的,而不能影响同层其他结构 19 attacked[0][i] = false; 20 attacked[1][a+i] = false; 21 attacked[2][n-a+i] = false; 22 } 23 } 24 } 25 } 26 27 int main(){ 28 cin>>n; //棋盘大小 29 tot = 0; 30 memset(attacked,0,sizeof(attacked)); 31 32 search(0);//从第0行开始 33 cout<<tot; 34 }
解题代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 // 2 // main.cpp 3 // 8 QUEENS 4 // 5 // Created by Yanbin GONG on 12/3/2018. 6 // Copyright © 2018 Yanbin GONG. All rights reserved. 7 // 8 9 #include <iostream> 10 #include <stdio.h> 11 #include <string> 12 #include <string.h> 13 #define N 8 14 15 int n; 16 bool vis[3][2*N]; 17 int r, c, kase; 18 int ans[N]; 19 20 void search(int cur) 21 { 22 if (cur == N) 23 { 24 printf("%2d ", ++kase); 25 for (int i = 0; i < N; i++) 26 printf("%d%s", ans[i]+1, (i==N-1) ? "\n" : " "); 27 return; 28 } 29 if (cur == c) search(cur+1); 30 else 31 { 32 for (int i = 0; i < N; i++) 33 if (!vis[0][i] && !vis[1][cur-i+N] && !vis[2][cur+i]) 34 { 35 ans[cur] = i; 36 vis[0][i] = vis[1][cur-i+N] = vis[2][cur+i] = 1; 37 search(cur+1); 38 vis[0][i] = vis[1][cur-i+N] = vis[2][cur+i] = 0; 39 } 40 } 41 } 42 43 int main() 44 { 45 scanf("%d", &n); 46 while (n--) 47 { 48 scanf("%d%d", &r, &c); 49 r--; 50 c--; 51 memset(vis, 0, sizeof(vis)); 52 vis[0][r] = 1; 53 vis[1][c-r+N] = 1; 54 vis[2][c+r] = 1; 55 ans[c] = r; 56 kase = 0; 57 printf("SOLN COLUMN\n"); 58 printf(" # 1 2 3 4 5 6 7 8\n\n"); 59 search(0); 60 if (n) printf("\n"); 61 } 62 return 0; 63 }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
· 手把手教你更优雅的享受 DeepSeek
· 腾讯元宝接入 DeepSeek R1 模型,支持深度思考 + 联网搜索,好用不卡机!
· AI工具推荐:领先的开源 AI 代码助手——Continue
· 探秘Transformer系列之(2)---总体架构
· V-Control:一个基于 .NET MAUI 的开箱即用的UI组件库