DFS(剪枝) - Lead of Wisdom - HDU 6772
2020 Multi-University Training Contest 2 1010
题意:
T组测试数据。
给定n件物品,共有k种,每件物品有四种属性ai,bi,ci,di,
要从k种物品种,每种物品选择一件,
使得收益:
DMG=(100+i∈S∑ai)(100+i∈S∑bi)(100+i∈S∑ci)(100+i∈S∑di)
最大,输出最大收益。
输入:
首行包括一个正整数T,表示T组测试数据
每组数据首行包括两个正整数n,k,
接着n行数据,每行包括ti,ai,bi,ci,di,分别表示物品种类和物品的四个属性。
Sample Input
1
6 4
1 17 25 10 0
2 0 0 25 14
4 17 0 21 0
1 5 22 0 10
2 0 16 20 0
4 37 0 0 0
Sample Output
297882000
数据范围:
1≤T≤10,1≤n,k≤50,1≤ti≤k,0≤ai,bi,ci,di≤100
分析:
记第i种装备的数量为cnti,
若cnti>0,那么选择该物品一定优于不选择该物品。
故总方案数为∏i=1kmax(cnti,1),其中∑i=1kcnti≤50,
最坏情况为所有cnti均相等时,∏i=1kmax(cnti,1)取最值,
假设它们都等于x,则方案总数为xxn,当x取3时,最大值为33n,
当n=50时,大约在108级别,仍然是可行的计算量。因此,可以考虑爆搜。
注意!!!:
对于数量为0的某种物品,应当直接跳过,不能进入搜索,
假设第i种物品数量为0,那么当我们枚举第i−1种物品时,就会搜索出cnti−1个空节点,
代码:
#include<iostream>
#include<cstring>
#define ll long long
using namespace std;
const int N=55;
int T,n,k;
int cnt[N];
ll ans;
int ne[N];
struct node
{
int a,b,c,d;
}w[N][N];
void dfs(int u,int a,int b,int c,int d)
{
if(u>k)
{
ll res=(ll )a*b*c*d;
ans=max(ans,res);
return ;
}
if(!cnt[u])
{
dfs(ne[u],a,b,c,d);
return ;
}
for(int i=1;i<=cnt[u];i++)
dfs(u+1,a+w[u][i].a,b+w[u][i].b,c+w[u][i].c,d+w[u][i].d);
}
int main()
{
cin>>T;
while(T--)
{
memset(cnt,0,sizeof cnt);
memset(ne,0,sizeof ne);
ans=0;
cin>>n>>k;
for(int i=1;i<=n;i++)
{
int t;
cin>>t;
cnt[t]++;
cin>>w[t][cnt[t]].a>>w[t][cnt[t]].b>>w[t][cnt[t]].c>>w[t][cnt[t]].d;
}
int last=k+1;
for(int i=k;i;i--)
{
ne[i]=last;
if(cnt[i]) last=i;
}
dfs(1,100,100,100,100);
printf("%lld\n",ans);
}
return 0;
}