数据结构与算法实验题 9.1 K 歌 DFS+剪枝
数据结构与算法实验题 K 歌
★实验任务
3* n 个人(标号1~ 3 * n )分成 n 组 K 歌。有 m 个 3 人组合,每个组合都对应一个分数,你能算出最大能够得到的总分数么?
★数据输入
输入的第 1 行是一个正整数 n 和 m(1<= n <=6 , n<=m<= C(3*n,3) 组合数) ,输入的第2~m+1行每行包括四个正整数a,b,c,s(1<=a , b ,c <=3 *n, a,b,c不相等,1<=s<=10 ^8)表示组合(a,b,c)可以获得分数 s。
输入示例
3 3
1 2 3 1
4 5 6 2
★实验任务
3* n 个人(标号1~ 3 * n )分成 n 组 K 歌。有 m 个 3 人组合,每个组合都对应一个分数,你能算出最大能够得到的总分数么?
★数据输入
输入的第 1 行是一个正整数 n 和 m(1<= n <=6 , n<=m<= C(3*n,3) 组合数) ,输入的第2~m+1行每行包括四个正整数a,b,c,s(1<=a , b ,c <=3 *n, a,b,c不相等,1<=s<=10 ^8)表示组合(a,b,c)可以获得分数 s。
★数据输出
输出可以获得的最大分数。(题目保证有一组解。)输入示例
3 3
1 2 3 1
4 5 6 2
7 8 9 3
★输出示例
6
给出另外一组数据
3 5
1 2 3 2
4 5 6 5
1 4 5 3
2 3 6 7
7 8 9 1
输出
11
DFS+剪枝
用DFS进行遍历,然后如果不进行剪枝的话,当C(18,3)=816 种情况全部出来时,时间复杂度将高达 816^6。
那么如何进行剪枝?
取其中所有S中的最大值,最好情况下是DFS中该叶节点之后的所有都取到这个最大值,如果这个最好的情况都小于等于答案,那么此路显然不可能是最优解。
详见代码吧。。。。
#include<cstdio> const int MAXN=1024; int n,m; bool exist[19]={0}; int ans=0; int maxs=0; struct combination { int a,b,c; int s; }data[MAXN]; inline void setExist(bool a,int i) { exist[data[i].a]=exist[data[i].b] =exist[data[i].c]=a; } void dfs(int cur,int now_c,int sum) { if(((n-now_c)*maxs+sum)<=ans) //剪枝 return; if(now_c==n) { if(ans<sum) ans=sum; return; } int i; for(i=cur;i<m;i++) { if( exist[data[i].a] ==false && exist[data[i].b] ==false &&exist[data[i].c]==false) { setExist(1,i); dfs(i+1,now_c+1,sum+data[i].s); setExist(0,i); } } } int main() { scanf("%d%d",&n,&m); int i; for(i=0;i<m;i++) { scanf("%d%d%d%d",&data[i].a,&data[i].b,&data[i].c,&data[i].s); if(maxs< data[i].s) maxs=data[i].s; } dfs(0,0,0); printf("%d\n",ans); }
新 blog : www.hrwhisper.me