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