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;
}

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

时间: 2024-10-19 14:47:09

ACM:回溯法,八皇后问题,素数环的相关文章

回溯法之八皇后问题简单理解

回溯法,简单理解就是有源可溯.基本思想要借鉴穷举法,但是它不是一味地穷举,当发现某一步不符合条件时,这一步后面的穷举操作就不进行了(俗称“剪枝”),我自己把它叫做动态穷举法.假设第一个步骤可行,那么执行第二个步骤,第三个......如果其中第三个步骤不行,那么我们再回过来(回溯),第二个步骤换一种方法尝试,然后再重新第三个步骤,第四个......直到完成任务要求为止. 这里,以八皇后问题为例.试图把回溯法讲清楚. 注意:递归应该是一种算法结构,回溯法是一种算法思想. 何为八皇后问题? (百度百科

回溯法和八皇后问题

一.回溯法 回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标.但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”. 二.八皇后问题 (一)问题描述 在国际象棋中,皇后是最强大的一枚棋子,可以吃掉与其在同一行.列和斜线的敌方棋子.比中国象棋里的车强几百倍,比她那没用的老公更是强的飞起(国王只能前后左右斜线走一格). 八皇后问题是这样一个问题:将八个皇后摆在一张8*

算法学步:回溯法-8皇后问题

问题描述: 有八个皇后(可以当成八个棋子),如何在 8*8 的棋盘中放置八个皇后,使得任意两个皇后都不在同一条横线.纵线或者斜线上 做法: 从第一行开始,一行一行地考虑,这样起码可以保证皇后不在同一行: 考虑下面的每一行的时候,需要让新增加的棋子不在前面添加的棋子的左下.正下.右下,即新增加的棋子的列不等于前面棋子的列,它的行号+列号不等于前面棋子的行号加列号(不在左下),|行号-列号|不等于之前棋子的|行号-列号|(不在右下): 如果该行所有位置都不符合要求,则回溯到前一行,改变皇后的位置,继

LeetCode 31:递归、回溯、八皇后、全排列一篇文章全讲清楚

本文始发于个人公众号:TechFlow,原创不易,求个关注 今天我们讲的是LeetCode的31题,这是一道非常经典的问题,经常会在面试当中遇到.在今天的文章当中除了关于题目的分析和解答之外,我们还会详细解读深度优先搜索和回溯算法,感兴趣的同学不容错过. 链接 Next Permutation 难度 Medium 描述 实现C++当中经典的库函数next permutation,即下一个排列.如果把数组当中的元素看成字典序的话,那下一个排列即是字典序比当前增加1的排列.如果已经是字典序最大的情况

【Python】生成器、回溯和八皇后问题

八皇后问题: 把N个皇后,放在N*N的棋盘上面,从第一行往下放,每个皇后占一行,同时,每个皇后不能处在同一列,对角线上,有多少种放置方法. 思路: 典型的回溯问题: 1.当要放置最后一个皇后时候,默认前N-1个皇后已经全部放置好了,那么验证在第N行上的每个位置是否可行,即是否与之前的皇后在同一列或者对角线即可: 2.如果放置的不是最后一个皇后,则回溯.回溯至刚开始放第一个元素时候,然后不断的返回上一层.每一层都认为下一层传递给自己的是正确的信息 1 def isconflict(state, n

迷宫回溯和八皇后问题

递归的概念 简单的说:递归就是方法自己调用自己,每次调用同时传入不同的变量,递归有助于编程者解决复杂的问题,同时可以让代码变得简洁 package recusion; public class RecursionTest { public static void main(String[] args) { test(5); int i = factorial(5); System.out.println(i); } //打印问题 //当程序执行到一个方法时,就会开辟一个独立的栈空间 public

回溯法---n皇后问题(4)

body { font-family: 微软雅黑,"Microsoft YaHei", Georgia,Helvetica,Arial,sans-serif,宋体, PMingLiU,serif; font-size: 10.5pt; line-height: 1.5; } html, body { } h1 { font-size:1.5em; font-weight:bold; } h2 { font-size:1.4em; font-weight:bold; } h3 { fon

每天刷个算法题20160519:回溯法解八皇后

版权所有.所有权利保留. 欢迎转载,转载时请注明出处: http://blog.csdn.net/xiaofei_it/article/details/51502622 为了防止思维僵化,每天刷个算法题.已经刷了几天了,现在发点代码. 我已经建了一个开源项目,每天的题目都在里面: https://github.com/Xiaofei-it/Algorithms 绝大部分算法都是我自己写的,没有参考网上通用代码.读者可能会觉得有的代码晦涩难懂,因为那是我自己的理解. 最近几天都是在写一些原来的东西

八皇后问题-回溯法(matlab)

1.问题描述 八皇后问题是十九世纪著名数学家高斯于1850年提出的.问题是:在8*8的棋盘上摆放8个皇后,使其不能互相攻击,即任意的两个皇后不能处在同意行,同一列,或同意斜线上. 2.matlab代码 function PlaceQueen(row,stack,N)%回溯法放置皇后 if row>N PrintQueen(N,stack);%打印棋盘 else for col=1:N stack(row)=col; if row==1||Conflict(row,col,N,stack)%检测是

回溯法求解八皇后问题---(初步、未优化)

首先介绍一下回溯算法: 定义来自<百度百科>......名字着很高大上,实际上就是试探法,逐步试错找到最终的可行解. 重要的一点是解空间通常是在搜索可行解过程中动态产生的,所以程序中通常利用到递归的算法,如后面介绍的八皇后问题.这点区别与于前段时间所写的模拟退火算法,模拟退火是首先确定解空间,然后以一定的概率接受当前发现的次优解,从而有更大的可能避免局部最优而得到全局最优. 简单介绍一下八皇后问题: 在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或