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

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);
}


posted @ 2013-11-12 10:27  hr_whisper  阅读(255)  评论(0编辑  收藏  举报