ACM:回溯,八皇后问题,素数环

简介:

(一)八皇后问题
(1)回溯

#include <iostream>
#include <string>

#define MAXN 100

using namespace std;

int tot = 0, n = 8;
int C[MAXN];

void search(int cur) {
	if(cur == n) ++tot;       //递归边界,仅仅要走到了这里。全部皇后必定不冲突
	else for(int i = 0; i < n; ++i) {
		int ok = 1;
		C[cur] = i;     //尝试把第cur行的皇后放在第i列
		for(int j = 0; j < cur; ++j) {     //检查是否和前面的皇后冲突
			if(C[cur] == C[j] || cur-C[cur] == j-C[j] || cur+C[cur] == j+C[j]) {
				ok = 0;
				break;
			}
		}
		if(ok)  search(cur+1);     //假设合法,则继续递归
	}
}

int main() {
	search(0);
	cout << tot << endl;
	return 0;
}



(2)利用二维数组优化的回溯法

#include <iostream>
#include <string>

#define MAXN 100

using namespace std;

int tot = 0, n = 8;
int vis[3][MAXN], C[MAXN];    

void search(int cur) {
	if(cur == n) ++tot;
	else for(int i = 0; i < n; ++i) {
		if(!vis[0][i] && !vis[1][cur+i] && !vis[2][cur-i+n]) {    //利用二维数组直接推断
			C[cur] = i;
			vis[0][i] = vis[1][cur+i] = vis[2][cur-i+n] = 1;   //改动全局变量
			search(cur+1);
			vis[0][i] = vis[1][cur+i] = vis[2][cur-i+n] = 0;   //这里一定要改回来!
		}
	}
}

int main() {
	memset(vis, 0, sizeof(vis));
	search(0);
	cout << tot << endl;
	return 0;
}

在上面的程序中,vis数组表示已经放置的皇后占领了哪些列、主对角线和副对角线。

一般的在回溯法中,假设改动了全局变量vis数组,那么递归调用结束后一定要改动回来!由于在解答树中,假设下一层不满足条件,那么就须要回溯。那么就要把改动过的vis给改回来,那样,才干继续进行下一次的推断!!!


(二)素数环

题目:输入正整数n,把整数1。2,3,...,n组成一个环。使得相邻两个整数之和均为素数。

输出时从整数1開始逆时针排列。

同一个环应该恰好输出一次。

典型的回溯法,代码例如以下:

#include <iostream>
#include <algorithm>
using namespace std;

const int MAXN = 1000;
int isp[MAXN], vis[MAXN], A[MAXN], n;

int is_prime(int x) {    //推断一个数是否为素数
	for(int i = 2; i*i <= x; ++i) {
		if(x % i == 0) return 0;
	}
	return 1;
}

void dfs(int cur) {
	if(cur == n && isp[A[0] + A[n-1]]) {
		for(int i = 0; i < n; ++i) cout << A[i] << " ";
		cout << endl;
	}else {
		for(int i = 2; i <= n; ++i) {
			if(!vis[i] && isp[i + A[cur-1]]) {
				A[cur] = i;   //数字i满足条件,所以第cur个位置能够放数字i
				vis[i] = 1;
				dfs(cur+1);
				vis[i] = 0;   //跟上题一样。一定不能忘记把vis的值改回来,原因见上一题的代码凝视
			}
		}
	}
}

int main() {
	memset(vis, 0, sizeof(vis));   //递归调用之前,一定要把vis函数清0
	cin >> n;
	for(int i = 2; i <= 2*n; ++i) isp[i] = is_prime(i);   //推断一个数不是质数。为了方便后推断
	A[0] = 1;   //从标题中的规定的第一个数字1开始
	dfs(1);     //所以递归调用位置的1开始,而不是从位置0开始,因为数字第一位置已被确定是1
	return 0;
}




本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5037127.html,如需转载请自行联系原作者


相关文章
|
7月前
|
算法 Android开发 索引
LeetCode 周赛上分之旅 #44 同余前缀和问题与经典倍增 LCA 算法
学习数据结构与算法的关键在于掌握问题背后的算法思维框架,你的思考越抽象,它能覆盖的问题域就越广,理解难度也更复杂。在这个专栏里,小彭与你分享每场 LeetCode 周赛的解题报告,一起体会上分之旅。
52 0
|
8天前
|
算法
代码随想录算法训练营第五十六天 | LeetCode 647. 回文子串、516. 最长回文子序列、动态规划总结
代码随想录算法训练营第五十六天 | LeetCode 647. 回文子串、516. 最长回文子序列、动态规划总结
30 1
|
8月前
|
算法 Android开发
LeetCode 周赛上分之旅 #38 结合排序不等式的动态规划
学习数据结构与算法的关键在于掌握问题背后的算法思维框架,你的思考越抽象,它能覆盖的问题域就越广,理解难度也更复杂。在这个专栏里,小彭与你分享每场 LeetCode 周赛的解题报告,一起体会上分之旅。
60 0
|
人工智能 算法 测试技术
LeetCode 双周赛 101,DP / 中位数贪心 / 裴蜀定理 / Dijkstra / 最小环
这周比较忙,上周末的双周赛题解现在才更新,虽迟但到哈。上周末这场是 LeetCode 第 101 场双周赛,整体有点难度,第 3 题似乎比第 4 题还难一些。
66 0
|
人工智能 算法 搜索推荐
LeetCode 周赛 338,贪心 / 埃氏筛 / 欧氏线性筛 / 前缀和 / 二分查找 / 拓扑排序
大家好,我是小彭。 上周末是 LeetCode 第 338 场周赛,你参加了吗?这场周赛覆盖的知识点很多,第四题称得上是近期几场周赛的天花板。
80 0
|
算法
状态压缩DP
复习acwing算法基础课的内容,本篇为讲解基础算法:动态规划——状态压缩DP,关于时间复杂度:目前博主不太会计算,先鸽了,日后一定补上。
126 0
状态压缩DP
|
存储 Java Python
ACM 选手图解 LeetCode 有序数组的平方
一个按非递减顺序排序的整数数组 nums,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。
ACM 选手图解 LeetCode 有序数组的平方
|
人工智能 算法 机器人
算法模板:动态规划之线性DP
线性动态规划,是较常见的一类动态规划问题,其是在线性结构上进行状态转移,这类问题不像背包问题、区间DP等有固定的模板。 线性动态规划的目标函数为特定变量的线性函数,约束是这些变量的线性不等式或等式,目的是求目标函数的最大值或最小值。 下面 我来详细讲解 线性DP 的几个常见模型
算法模板:动态规划之线性DP
[解题报告]《算法零基础100讲》(第15讲) 二分快速幂
[解题报告]《算法零基础100讲》(第15讲) 二分快速幂
[解题报告]《算法零基础100讲》(第15讲) 二分快速幂
[解题报告]《算法零基础100讲》(第26讲) 字符串算法(六) - 回文串
[解题报告]《算法零基础100讲》(第26讲) 字符串算法(六) - 回文串