SDUT 2860-生日Party(BFS)

生日Party

Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^

题目描述

Sherlock的生日即将来临,Sherlock打算邀请几个好友来参加自己的生日Party。为了让Party尽可能的happy,经过Sherlock的调查发现每个好友都有一个happy值。而且Sherlock的好友之间也存在复杂的关系,当好友中的某两个人同时出现在Party的时候,会产生一个额外的happy值,幸亏Sherlock好友不算多,Sherlock打算邀请部分或全部好友(也可能一个都不邀请),好让Party的happy值最高

输入

有多组数据,首先一个整数T表示所给数据的组数。每组数据第一行一个整数n(0<n<=15),表示Sherlock的好友人数。第二行n个整数依次表示每个好友如果来参加Party将会产生的happy值,接下来n行,每行n个整数,第i行的第j个整数表示当第i个好友和第j个好友同时参加party是产生的额外happy值
注意,所给数据中的happy值的范围为(-100~100)

输出

每组数据输出一行,Sherlock的Party最高的happy值

示例输入

4
2
1 2
0 -2
-2 0
3
-1 -1 0
0 1 1
1 0 1
1 1 0
3
1 1 1
0 -1 -1
-1 0 -1
-1 -1 0
3
-1 -1 -1
0 -2 -2
-2 0 -2
-2 -2 0

示例输出

2
1
1
0



之前一直在往dp方面想,结果一直推不出状态转移方程。。(sad 我dp就是个渣啊)而且mjj也说这是dp 防ak的 后来突然看到scf用暴搜过的!好吧我承认我也想过但前天才学的bfs之前也敲不出来,话说回来这题暴搜的思路也是很灵异的,对于第i个朋友,有两种状态,所以搜完一轮复杂度为O(2^15) 不需要标记数组,硬搜救可以了

 
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
typedef struct node
{
	int a[20],ans,x,top;//a数组里面放参加party的朋友的编号
};
int ma[20][20];
int fri[20],Max,n;
void bfs()
{
	node  t,v;
	queue <node> Q;
	t.top=0;t.ans=0;t.x=-1;
	Q.push(t);
	while(!Q.empty())
	{
		v=Q.front();Q.pop();
		if(v.x==n-1)//每选完一轮更新一下最大值
		{
			if(Max<v.ans)
				Max=v.ans;
			continue;
		}
		//两个搜索方向,要么选此人,要么不选
		t.x=v.x+1;//不选第i个人
		t.ans=v.ans;
		t.top=v.top;
		for(int i=0;i<v.top;i++)
			t.a[i]=v.a[i];
		Q.push(t);//选第i个人
		t.top=v.top+1;
		t.a[v.top]=t.x;
		t.ans=v.ans+fri[t.x];
		for(int i=0;i<v.top;i++)
			t.ans+=ma[t.a[i]][t.x];
		Q.push(t);
	}
}
int main()
{
	int T,i,j;
	cin>>T;
	while(T--)
	{
		cin>>n;
		for(i=0;i<n;i++)
			cin>>fri[i];
		for(i=0;i<n;i++)
			for(j=0;j<n;j++)
			cin>>ma[i][j];
		Max=-1;
		bfs();
		if(Max<0)
			cout<<"0"<<endl;
		else
			cout<<Max<<endl;

	}
	return 0;
}




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值