数据结构与算法实验题 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);
}