算法设计与分析 实验六 回溯法

1.迷宫:给定一个 N×M 方格的迷宫,迷宫里有T处障碍,障碍处不可通过。给定起点坐标和终点坐标,问: 每个方格最多经过1次,有多少种从起点坐标到终点坐标的方案。在迷宫中移动有上、下、左、右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。

入:输入的第一行包含三个整数N、M和T (1≤N,M≤5,0≤T<N*M),其中 N 代表行数,M 代表列数,T 代表障碍总数。

第二行起点坐标SX、SY (1≤SXN,1≤SYM),终点坐标FX、FY (1≤FXN,1≤FYM) 。

接下来T行,每行为障碍点的坐标X, Y (1≤XN,1≤YM) 。

出:输出仅一个整数,表示从起点坐标到终点坐标的方案总数。

入:2 2 1   1 1 2 2  1 2    出:1

#include
#include
#include
using namespace std;
int shuzu1[6][6];
bool shuzu2[6][6];
int dx[4]={0,0,1,-1}; int dy[4]={-1,1,0,0}; int t,n,m,x,y,sum,fx,fy,sx,sy;
void hanshu(int x,int y);
int main(){
    cin>>n>>m>>t;
    for(int i=1;i<=n;i++){
    	for(int j=1;j<=m;j++){
    		shuzu1[i][j]=1;
		}
	}
    cin>>sx>>sy>>fx>>fy;
    for(int i=1;i<=t;i++){
        cin>>x>>y;
        shuzu1[x][y]=0;
    }
    hanshu(sx,sy);
    cout<

2.自然数的拆分问题:任何一个大于 1 的自然数 n ,总可以拆分成若干个小于 n 的自然数之和。现在给你一个自然数 n ,要求你将 n 拆分成一些数字的和。每个拆分后的序列中的数字从小到大排序。然后你需要输出这些序列,其中字典序小的序列需要优先输出。

入:输入一个整数 n(1 <= n <= 8),表示需要拆分的自然数。

出:输出若干个的加法式子。

入:7   出:1+1+1+1+1+1+1    1+1+1+1+1+2 ……..   3+4

#include
#include
#include
using namespace std;
int shuzu1[9];
int n;
void out(int a){
	for(int i=0;i>n){
		fx1(1,0,0);
	}
	return 0;
}

3.选数:已知 n 个整数 x1,x2,  ·  ··,xn,以及 1个整数 kk<n)。从 n 个整数中任选 k 个整数相加,可分别得到一系列的和。例如当 n=4k=3,4 个整数分别为 3,7,12,19 时,可得全部的组合与它们的和为:3+7+12=22

3+7+19=29    7+12+19=38    3+12+19=34

现在,要求你计算出和为素数共有多少种。例如上例,只有一种的和为素数:3+7+19=29

入:第一行两个空格隔开的整数 n,k,(1n≤20,k<n)。第二行 n 个整数,分别为 x1,x2,· · · ,xn (1≤xi≤5×106)。

出:输出一个整数,表示种类数。

入:4 3   3 7 12 10    出:1

#include
#include
#include
using namespace std;
int n,k,temp,sum;int shuzu1[20];
int fx1(int a) {
	for(int i=2; i>n>>k;
	for(int i=1; i<=n; i++) {
		cin>>shuzu1[i];
	}
	fx2(k,0);
	cout<

4.好奇诡的游戏:这个游戏类似象棋,但是只有黑白马各一匹,在点 x1,y1 和 x2,y2 上。它们得从点 x1,y1 和 x2,y2 走到 (1,1) 。这个游戏与普通象棋不同的地方是:马可以走“日”,也可以像象走“田”。现在想知道两匹马到 (1,1) 的最少步数,你能解决这个问题么?

入:第1行:两个整数x1,y1  第2行:两个整数x2,y2      (1≤x1,y1,x2,y2≤20)

出:第1行:黑马到(1,1)的步数  第2行:白马到(1,1)的步数  假设棋盘为20*20

入:12 16   18 10    出:8  9

#include
#include
#include
#include
using namespace std;
class point{
	public:
		int x,y;
};
int n=20; int dx[]={2,2,2,2,1,1,-1,-1,-2,-2,-2,-2};
int dy[]={-2,-1,1,2,-2,2,-2,2,-2,-1,1,2}; int x1,y1,x2,y2,temp1,temp2;
int x,y; int x_temp,y_temp; int shuzu1[22][22];
bool shuzu2[22][22];
queue q;
int fx1(int a,int b){
	memset(shuzu2,false,sizeof(shuzu2));
	memset(shuzu1,false,sizeof(shuzu1));
	while(!q.empty()){
		q.pop();
	}
	q.push((point){a,b});
	shuzu2[a][b]=true;
	while(!q.empty()){
		x=q.front().x;
		y=q.front().y;
		q.pop();
		if(x+y==2){
			return shuzu1[1][1];
		}
		for(int i=0;i<12;i++){
			x_temp=x+dx[i];
			y_temp=y+dy[i];
			if(x_temp<=0 || x_temp>n || y_temp<=0 || y_temp>n){
				continue;
			}
			if(shuzu2[x_temp][y_temp]==true){
				continue;
			}
			shuzu1[x_temp][y_temp]=shuzu1[x][y]+1;
			shuzu2[x_temp][y_temp]=true;
			q.push((point){x_temp,y_temp});
		}
	}
}
int main(){
	cin>>x1>>y1>>x2>>y2;
	temp1=fx1(x1,y1);temp2=fx1(x2,y2);
	cout<

5.N皇后问题:规定当两个皇后出现在同一行,同一列,或者同一条对角线上时,它们会互相攻击。 现在要在一个 N×N 的棋盘上放置 N 个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,请问有多少种放置方法。

入:包含多组测试数据。 每组数据输入一行,仅包含一个整数 N (1 <= N <= 13)。

出:每组数据输出一行,包含一个整数,表示放置方案总数。

入:8   6   13    出:92   4    73712

#include
#include
#include
#include
using namespace std;
int n,sum;int shuzu1[500];
bool shuzu2[500];
void fx1(int m,int n) {
	if(m==n) {
		sum++;
		return;
	}
	for(int i=0; i> n) {
		sum=0;
		memset(shuzu1,0,sizeof(shuzu1));
		memset(shuzu2,1,sizeof(shuzu2));
		fx1(0,n);
		cout<

6.吃奶酪:房间里放着 n 块奶酪。一只小老鼠要把它们都吃掉,问至少要跑多少距离?老鼠一开始在 (0,0)点处。

入:第一行有一个整数,表示奶酪的数量 n

第 2 到第 (n+1) 行,每行两个实数,第 (i+1) 行的实数分别表示第 i 块奶酪的横纵坐标 xi,yi

对于全部的测试点,保证 1n15,|xi|,|yi|200,小数点后最多有 3位数字。

出:输出一行一个实数,表示要跑的最少距离,保留 2 位小数。

入:4   1 1   1 -1   -1 1   -1 -1     出:7.41

#include
#include
#include
#include
using namespace std;
int n;
double shuzu1[17], shuzu2[17]; double dp[17][1 << 17];
const int MAX = 2e9;
int fx1(int a, int b) {
	return a & (1 << b);
}
int fx2(int a, int b) {
	return a & (~(1 << b));
}
double suan(double x1, double y1, double x2, double y2) {
	return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
void dfs(int a, int b) {
	if (dp[a][b] != -1) {
		return;
	}
	dp[a][b] = MAX;
	for (int i = 0; i < n; ++i) {
		if (i == a) {
			continue;
		}
		if (!fx1(b, i)) {
			continue;
		}
		dfs(i, fx2(b, a));
		dp[a][b] = min(dp[a][b], dp[i][fx2(b, a)] + suan(shuzu1[i], shuzu2[i], shuzu1[a], shuzu2[a]));
	}
}
int main() {
	cin >> n;
	for (int i = 0; i < n; ++i) {
		cin >> shuzu1[i] >> shuzu2[i];
	}
	for (int i = 0; i < n; ++i) {
		for (int j = 1; j < (1 << n); ++j) {
			dp[i][j] = -1;
		}
	}
	for (int i = 0; i < n; ++i) {
		dp[i][1 << i] = suan(0, 0, shuzu1[i], shuzu2[i]);
	}
	for (int i = 0; i < n; ++i) {
		dfs(i, (1 << n) - 1);
	}
	double sum = MAX;
	for (int i = 0; i < n; ++i) {
		sum = min(sum, dp[i][(1 << n) - 1]);
	}
	printf("%.2f\n",sum);
	return 0;
}

你可能感兴趣的:(算法,算法,c++)