第五章实践报告

1、实践题目:工作分配问题

2、问题描述:

设集合S={x1,x2,…,xn}是一个正整数集合,c是一个正整数,子集和问题判定是否存在S的一个子集S1,使S1中的元素之和为c。试设计一个解子集和问题的回溯法。

输入格式:

输入数据第1行有2个正整数n和c,n表示S的大小,c是子集和的目标值。接下来的1行中,有n个正整数,表示集合S中的元素。 是子集和的目标值。接下来的1 行中,有n个正整数,表示集合S中的元素。

输出格式:

输出子集和问题的解,以空格分隔,最后一个输出的后面有空格。当问题无解时,输出“No Solution!”。

在这里给出一组输入。例如:

3
10 2 3
2 3 4
3 4 5

输出样例:

在这里给出相应的输出。例如:

9

3、算法描述:

本道题的解空间由长度为 n 的向量组成,第 i 个向量的取值为 j 个工人完成第 i 个任务所需的费用。以样例作解释,画出其解空间树为:

用数组 vis[n] 来判断是否第 j 个工人已经被分配了工作,初始化数组为0,如果已经被分配了工作则置为1。利用该数组进行约束剪枝。

限界函数利用两个int类型的变量 cnt 和 ans,cnt 表示当前的花费,初始化为0,ans 作为最终答案,初始化为 for(int i = 1; i <= n; i++) ans += a[i][i]。如果cnt 小于ans,那么就更新ans。

附上代码:

#include<bits/stdc++.h>
using namespace std;
int n,ans;
int a[25][25];
int vis[25];
void backtrack(int t,int cnt)
{
	if(now>n&&cnt<ans)
	{
		ans=cnt;
		return ;
	}
	if(cnt<ans)
	for(int j=1;j<=n;j++)
		if(vis[j]==0)
		{
			vis[j]=1;
			backtrack(t+1,cnt+a[t][j]);
			vis[j]=0;
		}
}
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			cin>>a[i][j];
			vis[j]=0;
		}
		ans+=a[i][i];
	}
	backtrack(1,0);
	cout<<ans<<endl;
}

4、心得体会:

总的来说,这次实践让自己明白了自己在回溯法的学习上还是不够的,需要更深一步的理解才行。因为在编程的时候发现自己花费的时间还是比较长的。

原文地址:https://www.cnblogs.com/xwl2333/p/10160891.html

时间: 2024-10-27 13:38:25

第五章实践报告的相关文章

算法第五章实践报告

1. 实践题目 工作分配问题 2. 问题描述 设有n件工作分配给n个人.将工作i分配给第j个人所需的费用为cij . 设计一个算法,对于给定的工作费用,为每一个人都分配1 件不同的工作,并使总费用达到最小. 输入格式: 输入数据的第一行有1 个正整数n (1≤n≤20).接下来的n行,每行n个数,表示工作费用. 输出格式: 将计算出的最小总费用输出到屏幕. 输入样例: 在这里给出一组输入.例如: 3 10 2 3 2 3 4 3 4 5 输出样例: 在这里给出相应的输出.例如:   9 3. 算

【实践报告】算法第二章实践报告

实践报告任选一题进行分析. 1.实践题目: 7-1 二分查找 输入n值(1<=n<=1000).n个非降序排列的整数以及要查找的数x,使用二分查找算法查找x,输出x所在的下标(0~n-1)及比较次数.若x不存在,输出-1和比较次数. 输入格式:输入共三行: 第一行是n值: 第二行是n个整数: 第三行是x值. 输出格式:输出x所在的下标(0~n-1)及比较次数.若x不存在,输出-1和比较次数. 2.问题描述: 输入n值(1<=n<=1000).n个非降序排列的整数以及要查找的数x,使

C和指针 第十五章 错误报告perror和exit

15.1 错误报告 perror 任何一种程序都存在出错的可能,包括系统的函数库,当出现错误时,系统提示发生错误,标准库函数在一个外部整型变量中保存错误代码,然后把错误代码传给用户程序,提示错误原因.perror简化了向用户报告特定错误过程. void perror(char const * message); perror,接受字符串,先打印出这个字符串,然后在后面跟一个分号空格,然后打印出解释errno的错误代码的信息 #include <stdio.h> #include <err

第二章实践报告

1.实践题目:二分查找 2.问题描述: 输入n值(1<=n<=1000).n个非降序排列的整数以及要查找的数x,使用二分查找算法查找x,输出x所在的下标(0~n-1)及比较次数.若x不存在,输出-1和比较次数. 3.算法描述: while(left<=right){ //左右比较 int middle=(left+right)/2; //取中值 t++; //运算次数加一 if(x==a[middle]){ //查找值与数组middle位置的值相等时输出 cout<<midd

算法第二章实践报告

第一道题: 第一道题要求输出查找次数,一开始我们小组用了两个二分查找算法来实现一个返回下标,一个返回计数器的值.但后来经过老师指点,我们采取了全局变量,来作为计数器,其值也是查找次数. 第二道题: 第二道题要求找不到目标的时候可以返回最邻近的两个值的下标,所以我们又添加了i和j,在每次进行大小比较之后记住比较过的元素下标.最后只需要在找不到相应元素的时候输出i和j即可. 第三道题: 第三道题要求将两个序列重新整合之后再输出中位数.老师要求做出logn的算法,但因为对算法的不熟悉,我们小组在实践课

【实践报告】算法第三章实践报告

1.实践题目 7-2最大子段和 给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],-,a[n],求该序列如a[i]+a[i+1]+-+a[j]的子段和的最大值.当所给的整数均为负数时,定义子段和为0. 要求算法的时间复杂度为O(n). 2.问题描述 输入格式: 输入有两行: 第一行是n值(1<=n<=10000): 第二行是n个整数. 输出格式: 输出最大子段和. 输入样例: 在这里给出一组输入.例如: 6 -2 11 -4 13 -5 -2 输出样例: 在这里给出相应的输出.

第三章实践报告

实践题目:数字三角形 题目描述: 设计一个算法,计算出从三角形 的顶至底的一条路径(每一步可沿左斜线向下或右斜线向下),使该路径经过的数字总和最大. 算法描述:从下至上依次左右比较,大的那方和上面的数相加,直至第一列. 算法时间和空间复杂度分析:因为用到了双重循环,所以时间复杂度为o(n^2),同时使用了二维数组,所以空间复杂度也是o(n^2). 心得:这道题用从下至上的方法比较简单,要有逆向思维. 原文地址:https://www.cnblogs.com/ewerin/p/9943461.ht

算法第4章实践报告

1.实践题目 7-3 程序存储问题 (90 分) 2.问题描述 设有n 个程序{1,2,-, n }要存放在长度为L的磁带上.程序i存放在磁带上的长度是 li,1≤i≤n. 程序存储问题要求确定这n 个程序在磁带上的一个存储方案, 使得能够在磁带上存储尽可能多的程序. 对于给定的n个程序存放在磁带上的长度,计算磁带上最多可以存储的程序数. 输入格式: 第一行是2 个正整数,分别表示文件个数n和磁带的长度L.接下来的1行中,有n个正整数,表示程序存放在磁带上的长度. 输出格式: 输出最多可以存储的

算法第四章实践报告

1.选择第二题进行分析. 给定n位正整数a,去掉其中任意k≤n 个数字后,剩下的数字按原次序排列组成一个新 的正整数.对于给定的n位正整数a和正整数 k,设计一个算法找出剩下数字组成的新数最 小的删数方案. 输入 178543 4 输出132.问题描述:就是删掉指定数字中的一些数字,然后重新组成一个新的数使得这个数达到最小.3.算法描述:这个问题第一眼看下去容易想到对数组不停的排序然后不断删掉最大的,但是按着这个思路去做却发现,不断提取整型数组然后排序会比较复杂,因为要不断求余数等等,而且代码不