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

Posted stearm210

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法设计与分析 实验六 回溯法相关的知识,希望对你有一定的参考价值。

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<iostream>
#include<cstdlib>
#include<string>
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<<sum;
    return 0;
 
void hanshu(int x,int y)
    if(x==fx && y==fy)
        sum++;
        return;
    
    else
        for(int i=0;i<=3;i++)
            if(shuzu2[x+dx[i]][y+dy[i]]==0  && shuzu1[x+dx[i]][y+dy[i]]==1)
                shuzu2[x][y]=1;
                hanshu(x+dx[i],y+dy[i]);
                shuzu2[x][y]=0;
                
         
    

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<iostream>
#include<cstdlib>
#include<string>
using namespace std;
int shuzu1[9];
int n;
void out(int a)
	for(int i=0;i<a;i++)
		if(i==0)
			cout<<shuzu1[i];
		else
			cout<<"+"<<shuzu1[i];
		
	
	cout<<endl;
	return;

void fx1(int a,int b,int c)//从a开始选择
//b是总和,c是从c+1开始选择 
	if(a==n)
		return;
	
	if(b==n)
		out(c);
		return;
	
	for(int i=a;i<=n-b;i++)
		shuzu1[c]=i;//选择了什么数 
		fx1(i,b+i,c+1);
	

int main()
	while(cin>>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<iostream>
#include<cstdlib>
#include<string>
using namespace std;
int n,k,temp,sum;int shuzu1[20];
int fx1(int a) 
	for(int i=2; i<a; i++) 
		if(a%i==0) 
			return 0;
		
	
	return 1;

void fx2(int a,int b) 
	if(a==0) 
		temp+=fx1(sum);
	 else 
		b++;
		for(int i=b; i<=n; i++) 
			sum+=shuzu1[i];
			a--;
			fx2(a,i);
			sum-=shuzu1[i];
			a++;
		
	

int main() 
	cin>>n>>k;
	for(int i=1; i<=n; i++) 
		cin>>shuzu1[i];
	
	fx2(k,0);
	cout<<temp;
	return 0;

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<iostream>
#include<string>
#include<cstring>
#include<queue>
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<point> 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<<temp1<<endl;cout<<temp2<<endl;
	return 0;

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

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

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

入:8   6   13    出:92   4    73712

#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
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; i++) 
		if(!shuzu2[i])
			continue;
		
		bool temp = true;
		for(int j=0; j<m; j++) 
			if(shuzu1[j]==i)
				continue;
			 
			if(abs(m-j)==abs(shuzu1[j]-i)) 
				temp= false;
				break;
			
		
		if(temp) 
			shuzu1[m] = i;
			shuzu2[i] = false;
			fx1(m+1,n);
			shuzu2[i] = true;
		
	

int main() 
	while(cin >> n) 
		sum=0;
		memset(shuzu1,0,sizeof(shuzu1));
		memset(shuzu2,1,sizeof(shuzu2));
		fx1(0,n);
		cout<<sum<<endl;
	
	return 0;

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<iostream>
#include<algorithm>
#include<queue>
#include<cmath>
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;

以上是关于算法设计与分析 实验六 回溯法的主要内容,如果未能解决你的问题,请参考以下文章

算法设计与分析实验五-旅行商问题|实验六-n皇后问题

算法设计与分析实验五-旅行商问题|实验六-n皇后问题

算法设计与分析实验五-旅行商问题|实验六-n皇后问题

算法设计与分析——回溯法算法模板

[XJTUSE 算法设计与分析] 第五章 回溯法

算法设计与分析回溯法---八皇后问题(包含全排列)