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