算法设计与分析第五章 (回溯法)课后习题答案(c++)

目录

上机实验题

        问题一:求解填字游戏问题

        问题二:求解组合问题

        问题三:求解满足方程解问题(该题无解)

在线编程题

        问题一:求解会议安排问题

        问题二:求解最小机器重量设计问题1

        问题三:求解最小机器重量设计问题2

        问题四:求解密码问题 

        问题五:求解马走棋问题

        问题六:求解幸运的袋子问题


该文章是算法设计与分析(第二版)中各章的课后习题 主编 : 李春葆

在本文中,主要是对该书第五章-回溯法章节中的上机实验题以及在线编程题进行代码解答。

代码运行环境是:DEVc++

上机实验题

问题一:求解填字游戏问题

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

//素数,计算过程中可能用到的素数 
int a1[] = {2,3,5,7,11,13,17,19,23}; 
vector<int> a(a1,a1+10);
int result[4][4];
// coun 用于记录满足要求的方阵个数 
int coun = 0;
int tag[11] = {0};
bool panduan(int x, int y, int t)  //判断 t 是否为素数
{	 
	// tag[t] 判断 数字 t是否被使用 
	if(tag[t] == 1){
		return false;
	}
	if(x - 1 >= 0)
	{
		if(find(a.begin(),a.end(),t+result[x-1][y]) == a.end())
			return false;
	}
	if(y - 1 >= 0)
	{
		if(find(a.begin(),a.end(),t+result[x][y-1]) == a.end())
			return false;
	}
	return true;
}
void pushin(int x,int y){
	if(x == 3){
		coun++;
		cout<<"coun = "<<coun<<endl;
		
		//可以输出查看结果 
		for(int i = 0;i <= 2;i++)
		{
			for(int j = 0;j <= 2;j++)
			{
				cout << result[i][j] << " ";
			}
			cout << endl;
		}
		//system("pause");
		return;
	}else{
		//递归 
		for(int i = 1;i <= 10;i++){
			if(panduan(x,y,i)){
				result[x][y] = i;   // 标记 
				tag[i] = 1;   //将已经用过的数标记为置1
				if(y != 2){
					pushin(x,y+1);
				}else{
					//x+1换行 
					pushin(x+1,0);
				}
				result[x][y] = 0;
				tag[i] = 0;
			}
		}
	}
}
int main(){
	pushin(0,0);
	return 0;
}

 运行部分截图:

 问题二:求解组合问题

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
void dfs(int n,int r,int i,vector<int>  &a){
	if(a.size() == r){
		for(int j = 0 ; j < r ;j++){
			cout<<a[j]<<" ";
		}
		cout<<endl;
		return;
	}else{
		for(int k = i;k <= n;k++){
			a.push_back(k);
			dfs(n,r,k+1,a);
			a.pop_back();
		}
	}
}
int main(){
	int n,r;
	cin>>n>>r;
	while(n<r){
		cout<<"r 必须小于 n,请重新输入"<<endl;
		cin>>n>>r;
	}
	vector<int> a;
	dfs(n,r,1,a);
	return 0;
}

 运行截图:

问题三:求解满足方程解问题(该题无解)

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
//这题貌似没有正确的结果,真实老六。 
int coun = 0;
void dfs(int i,int a[]){
	if(i >= 5){
		if((a[1]*a[2]) - (a[3]*a[4]) + a[5] == 1){
			coun++;
			for(int p = 1;p <= 5;p++){
				cout<<a[p]<<" ";
			}
			cout<<endl;
		}
		return;
	}else{
		for(int j = i;j <= 5 ;j++){
			swap(a[i],a[j]);
			dfs(i+1,a);
			swap(a[i],a[j]);
		}
	}
}
int main(){
	int a[] = {0,1,2,3,4,5};
	dfs(1,a);
	cout<<"该方程解的个数为:"<<coun<<endl;
	return 0;
}

运行截图:

在线编程题

问题一:求解会议安排问题

#include<iostream>
#include<cstdio>
using namespace std;
#define MAX 20   
int n;
int ans, temp, counter;
struct classroom
{
	int start;
	int end;
};
/*
4
1 2
3 5 
1 4
4 5
*/ 
void dfs(classroom a[], int i)
{
	counter = 0;
	for (int j = 1; j <= n; j++)
	{
		if (a[j].start >= a[i].end)
		{
			int t=(a[j].end - a[j].start);
			temp += t;
			dfs(a, j);
			temp -=t;  //回溯
			counter++;
		}
	}
	if (counter == 0){
		if (temp>ans){
			ans = temp;
		}
	}
		
}

int main()
{
	cin >> n;
	classroom a[MAX];
	a[0].end = 0;
	for (int i = 1; i <= n; i++)
		cin >> a[i].start >> a[i].end;
	dfs(a, 0);
	cout <<"所有活动占用的最大时间为: "<< ans<<endl;
	return 0;
}

 运行截图:

问题二:求解最小机器重量设计问题1

 

#include<iostream>
#include<stdio.h>
 
using namespace std;
int w[100][100];//w[i][j]为第i个零件在第j个供应商的重量
int c[100][100];//c[i][j]为第i个零件在第j个供应商的价格
int bestx[100];//bestx[i]表示一次搜索到底后的最优解,用来存放第i个零件的供应商,
int x[100];//x[i]临时存放第i个零件的供应商
int cw = 0, cc = 0, bestw = 10000;
int cost;//限定价格
int n;//部件数
int m;//供应商数
 
/*
3 3 7
1 2 3
3 2 1
2 3 2
1 2 3
5 4 2
2 1 2
*/
void Backtrack(int t)
{
    int j;
    if (t > n)//搜索到叶子结点,一个搜索结束,所有零件已经找完
    {
        bestw = cw;//当前最小重量
        for (j = 1; j <= n; j++){
        	//拷贝对应的供货商 
        	bestx[j] = x[j];
		}
    }
    else
    {
        for (j = 1; j <= m; j++)
        {	
			if (cc + c[t][j] <= cost && cw + w[t][j] < bestw)
            {
                x[t] = j;
                cc += c[t][j];
                cw += w[t][j];
                Backtrack(t + 1);
                cc -= c[t][j];
                cw -= w[t][j];
            }
		} 
	}
}
 
int main()
{
    int i, j;
    cin >> n;
    cin >> m;
    cin >> cost;
//    请输入各部件的在不同供应商的重量:
    for (i = 1; i <= n; i++)
    {
        for (j = 1; j <= m; j++)
        {
            cin >> w[i][j];
        }
    }
    //cout << "请输入各部件的在不同供应商的价格:" << endl;
    for (i = 1; i <= n; i++)
    {
        for (j = 1; j <= m; j++)
        {
            cin >> c[i][j];
        }
    }
    Backtrack(1);
    cout << "每个部件的供应商为:" << endl;
    for (i = 1; i <= n; i++)
        cout << bestx[i] << ' ';
    cout << endl;
    cout<<"最小重量为:" << bestw;
    cout << endl;
    system("pause");
    return 0;
}

 运行截图:

问题三:求解最小机器重量设计问题2

#include<iostream>
#include<stdio.h>
 
using namespace std;
int w[100][100];//w[i][j]为第i个零件在第j个供应商的重量
int c[100][100];//c[i][j]为第i个零件在第j个供应商的价格
int bestx[100];//bestx[i]表示一次搜索到底后的最优解,用来存放第i个零件的供应商,
int x[100];//x[i]临时存放第i个零件的供应商
int cw = 0, cc = 0, bestw = 10000;
int cost;//限定价格
int n;//部件数
int m;//供应商数
 
/*
3 3 7
1 2 3
3 2 1
2 3 2
1 2 3
5 4 2
2 1 2
*/
void Backtrack(int t)
{
    int j;
    if (t > n)//搜索到叶子结点,一个搜索结束,所有零件已经找完
    {
        bestw = cw;//当前最小重量
        for (j = 1; j <= n; j++)
            bestx[j] = x[j];
    }
    else
    {
        for (j = 1; j <= m; j++)
        {	
        	int temp = 0;   //用于判断该供应商是否被选取 
        	for(int i = 1;i <= m;i++){
        		if(x[i] == j){
        			temp = 1;
				}
			} 
			if(temp != 1){  //当还没有在该供货商处购物时 
				if (cc + c[t][j] <= cost && cw + w[t][j] < bestw)
	            {
	                x[t] = j;
	                cc += c[t][j];
	                cw += w[t][j];
	                Backtrack(t + 1);
	                cc -= c[t][j];
	                cw -= w[t][j];
	            }
			} 
            
        }
    }
}
 
int main()
{
    int i, j;
    cin >> n;
    cin >> m;
    cin >> cost;
    //请输入各部件的在不同供应商的重量:
    for (i = 1; i <= n; i++)
    {
        for (j = 1; j <= m; j++)
        {
            cin >> w[i][j];
        }
    }
    //cout << "请输入各部件的在不同供应商的价格:" << endl;
    for (i = 1; i <= n; i++)
    {
        for (j = 1; j <= m; j++)
        {
            cin >> c[i][j];
        }
    }
    Backtrack(1);
    cout << "每个部件的供应商:" << endl;
    for (i = 1; i <= n; i++)
        cout << bestx[i] << ' ';
    cout << endl;
    cout <<"最小重量为:"<< bestw;
    cout << endl;
    return 0;
}

 运行截图:

问题四:求解密码问题 

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

//1 ABCDEFGHIJKL
//11700519 ZAYEXIWOVU
//3072997 SOUGHT
//1234567 THEQUICKFROG
int a[6];
char result[6] = {0};
int max1 = -1;
void dfs(int i,int len,string str,int n){
	if(i == 6){
		if(a[1] - pow(a[2],2) + pow(a[3],3) - pow(a[4],4) + pow(a[5],5) == n){
			int tmax = 0;
			for(int k = 1;k < 6;k++){
				char cc = a[k] +'A'-1;
				if(a[k] +'A'-1 < result[k]){
					break;
				}else if(a[k] +'A'-1 == result[k]){
					continue;
				}else{
					tmax = 1;
					break;
				}
			}
			if(tmax == 1){
				for(int k = 1;k < 6;k++){
					max1 = 1;
					char ch = a[k] + 'A' - 1;
					result[k] = ch;
				}
			}
		}
		return ;
	}else{
		for(int j = len-1;j >= 0 ;j--){
			//判断字母是否重复
			int chongfu = 0; 
			for(int k = 1;k < i;k++){
				if(a[k] == str[j] - 'A' + 1){
					chongfu = 1;
					break;
				}
			} 
			if(chongfu != 1){
				a[i] = 	str[j] - 'A' + 1;
				dfs(i+1,len,str,n);
				a[i] = 0;
			}
			
		}
	}
}
int main(){
	for(int k = 1 ; k < 6 ;k++){
		result[k] = 'A';
	}
	
	int n;
	string str = "";
	cin>>n>>str;
	int len = str.length();
	dfs(1,len,str,n);
	//输出结果 
	if(max1 == -1){
		cout<<"no solution";
	}else{
		cout<<"答案为:"<<endl; 
		for(int k = 1 ; k < 6 ;k++){
			cout<<result[k]<<" ";
		}
		cout<<endl<<"对应的数字为:"<<endl;
		for(int k = 1 ; k < 6 ;k++){
			cout<<result[k] - 'A' + 1<<" ";
		}
	}
	
	return 0;
}

运行截图:

问题五:求解马走棋问题

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
// 4 4
int sum = 0;
void dfs(int x,int y,int m,int n){
	if(x == m && y == n){
		sum++;
		return;
	}else{
		if(x+2 <= m && y+1 <= n){
			dfs(x+2,y+1,m,n);
		}
		if(x+1 <= m && y+2 <= n){
			dfs(x+1,y+2,m,n);
		}
	}
}
int main(){
	int m , n;
	cin>>m>>n;
	dfs(1,1,m,n); 
	cout<<"总共的方案数为:"<<sum;
	return 0;
}

 运行截图:

问题六:求解幸运的袋子问题

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int n,num = 1;
int sum = 0,mul = 1,result = 0;
vector<int> res;
vector<vector<int>> quchong;
//3 1 1 1
//4 1 1 2 3
//问题7 求解幸运的袋子问题
void dfs(int i,vector<int>& a){
	if(i > n){
		if(sum > mul){
			//去重 
			if(find(quchong.begin(),quchong.end(),res) == quchong.end()){
				//输出满足条件的结果 
				cout<<"方案 "<<num++<<endl; 
				for(auto h:res){
					cout<<h<<" ";
				}
				cout<<endl;
				//加入结果数组中 
				quchong.push_back(res);
				result++;
			}
		}
		return;
	}else{
		res.push_back(a[i]);
		sum += a[i];
		mul *= a[i];
		dfs(i+1,a);
		//回溯 
		res.pop_back();		
		sum -= a[i];
		mul /= a[i];
		dfs(i+1,a);
	}
}
int main(){
	cin>>n;
	vector<int> a(n+1);
	for(int i = 1 ; i <= n;i++){
		cin>>a[i];
	}
	sort(a.begin(),a.end());
	dfs(1,a);
	cout<<"幸运袋子的总个数为: "<<result<<endl;
	return 0;
}

运行截图;

  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是第四章的部分习题答案,希望对你有帮助。 1. 设计一个O(nlogn)时间复杂度的算法,找出一个整数数组中的最大差值,其中最大值必须位于最小值之后。 解答:可以使用分治法,将数组分成两部分,分别求出左边的最大值和右边的最小值,然后比较两个值之间的差值,取最大值即可。具体实现如下: ```python def max_diff(arr): if len(arr) < 2: return 0 mid = len(arr) // 2 left_max = max(arr[:mid]) right_min = min(arr[mid:]) return max(right_min - left_max, max_diff(arr[:mid]), max_diff(arr[mid:])) ``` 2. 设计一个算法,找出一个整数数组中的最大子序列和。 解答:可以使用动态规划法,定义一个状态数组dp,dp[i]表示以第i个元素结尾的最大子序列和,转移方程为:dp[i] = max(dp[i-1] + arr[i], arr[i])。最后返回dp数组中的最大值即可。具体实现如下: ```python def max_subarray(arr): if not arr: return 0 dp = [0] * len(arr) dp[0] = arr[0] for i in range(1, len(arr)): dp[i] = max(dp[i-1] + arr[i], arr[i]) return max(dp) ``` 3. 给定一个长度为n的整数序列,设计一个算法,找出其中第k大的数。 解答:可以使用快速排序的思想,每次选定一个pivot,将数组分成两部分,左边的元素都小于pivot,右边的元素都大于等于pivot。然后比较pivot的位置和k的大小,如果pivot的位置大于k,则在左边继续查找;如果pivot的位置小于k,则在右边继续查找。具体实现如下: ```python def quick_select(arr, k): if not arr or k > len(arr): return None pivot = arr[-1] left = [x for x in arr[:-1] if x < pivot] right = [x for x in arr[:-1] if x >= pivot] if len(right) == k - 1: return pivot elif len(right) > k - 1: return quick_select(right, k) else: return quick_select(left, k - len(right) - 1) ``` 4. 设计一个算法,找出一个无序整数数组中出现次数超过一半的数。 解答:可以使用摩尔投票法,遍历整个数组,维护一个候选数和计数器,如果当前元素等于候选数,则计数器加1;否则计数器减1。如果计数器归零,则将当前元素作为候选数。最后再遍历一遍数组,统计候选数的出现次数,如果出现次数超过一半,则返回该候选数。具体实现如下: ```python def majority_element(arr): if not arr: return None candidate = None count = 0 for num in arr: if count == 0: candidate = num count += (1 if num == candidate else -1) if arr.count(candidate) > len(arr) // 2: return candidate else: return None ``` 5. 设计一个算法,找出一个整数数组中的两个元素,使它们的和等于一个给定的数。 解答:可以使用哈希表,遍历整个数组,对于每个元素,如果它的补数已经在哈希表中,则返回它们的下标;否则将该元素加入哈希表中。具体实现如下: ```python def two_sum(arr, target): if not arr: return None table = {} for i, num in enumerate(arr): complement = target - num if complement in table: return (table[complement], i) else: table[num] = i return None ``` 希望这些答案能够帮助你解决算法设计与分析第四章的部分习题

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值