算法设计与分析 实验六 回溯法
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≤SX≤N,1≤SY≤M),终点坐标FX、FY (1≤FX≤N,1≤FY≤M) 。
接下来T行,每行为障碍点的坐标X, Y (1≤X≤N,1≤Y≤M) 。
出:输出仅一个整数,表示从起点坐标到终点坐标的方案总数。
入: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个整数 k(k < n)。从 n 个整数中任选 k 个整数相加,可分别得到一系列的和。例如当 n = 4,k = 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, (1≤n≤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。
对于全部的测试点,保证 1 ≤ n ≤ 15, |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;
以上是关于算法设计与分析 实验六 回溯法的主要内容,如果未能解决你的问题,请参考以下文章