1010:http://acm.hdu.edu.cn/showproblem.php?pid=6772
题意:你可以装备k种类型的装备(注意,是可以不装备的,每种类型只能装备一件),现在给你n个装备,然后你知道每一件装备的类型t和a,b,c,d四种属性。定义 (这里
) (S是所选装备的集合) 现在要你输出这n件装备组成的S中,DMG的最大值
思路:我们看一下范围,n,k<=50 ,不难想到枚举,我们把所有情况都枚举出来,挑最大值。这时,我们发现了困难,我不知道具体的k,我怎么写循环。这里不妨用递归来优化,我们一种装备一种装备的来挑选,在选定某种类型的某件装备后,我们去选下一种,一直到题目所给的k也选掉(最后代码里面不是这样,但是最初思路如此)。至此题目也就写出来了。
//team yglance+xhwl+TTD
#include<bits/stdc++.h>
typedef long long ll;
const ll mod=1e9+7;
const ll maxn=1e5+7;
const double pi=acos(-1);
using namespace std;
struct M//这个就是装备
{
int a,b,c,d;
};
vector< M > vec[55];//因为最多50种装备,这里按装备类型分类
int n=0,k=0;
ll mx=0;//答案
ll mxty=0;//虽然题目说一共有k种类型,但是万一只给了极少的类型,一直计算到k会浪费很多时间,这里是一个小小的优化,虽然小,但是不写,就会T掉
ll temp[4]={0};//这个就是到目前为止的a,b,c,d的和
//枚举
void solve(int q) //q是装备类型
{
if(q==mxty+1)//当枚举到第k+1时,就可以维护最大值了,因为只有k种装备。
{
mx=max(mx,(100+temp[0])*(100+temp[1])*(100+temp[2])*(100+temp[3]));
return ;
}
if(vec[q].size()==0)//如果没有这种装备,就跳过好了
{
solve(q+1);
}
else
{
for(int i=0;i<vec[q].size();i++)//对每种类型的每件装备进行枚举
{
//总属性增加
temp[0]+=vec[q][i].a;
temp[1]+=vec[q][i].b;
temp[2]+=vec[q][i].c;
temp[3]+=vec[q][i].d;
//递归下一种类型
solve(q+1);
//既然已经递归回来了,那么这件装备的属性就多了,减掉,为下件装备腾出位置
temp[0]-=vec[q][i].a;
temp[1]-=vec[q][i].b;
temp[2]-=vec[q][i].c;
temp[3]-=vec[q][i].d;
}
}
}
int main()
{
ios::sync_with_stdio(false);
//freopen("in.txt","r",stdin);
int t;
cin>>t;
while(t--)//10
{
mx=0;
mxty=0;
for(int i=0;i<k;i++)//刚刚忘记清零了
{
vec[i].clear();
}
memset(temp,0,sizeof(temp));
cin>>n>>k;
for(int i=0;i<n;i++)
{
M mm;
ll ty;
cin>>ty>>mm.a>>mm.b>>mm.c>>mm.d;
mxty=max(mxty,ty);
vec[ty].push_back(mm);
}
// for(int i=1;i<=k;i++)
// {
// for(int j=0;j<vec[i].size();j++)
// {
// cout<<i<<" "<<vec[i][j].a<<" "<<vec[i][j].b<<" "<<vec[i][j].c<<" "<<vec[i][j].d<<endl;
// }
// }
solve(1);
cout<<mx<<endl;
}
return 0;
}

京公网安备 11010502036488号