Root ::Regionals 2013 :: Africa/Middle East - Arab Contest 6757 - Cup of Cowards
现有5个人打一个怪物,怪物的血量为10^12,每个人每次攻击有会令怪物掉一定的血量,同时会产生一定的费用,并且每个人都有一个攻击次数上限,问击败怪物的最少花费。若花费相同,则要求对怪物的伤害溢出最小
这个问题其实是一个5个物品的多重背包问题,但是由于背包容量太大(10^12),所以无法dp做。
于是直接搜索,加一些优化。
1. 先尝试性价比高的人,即攻击力高费用低的人
2. 若剩下的所有人的所有攻击均不能将boss打死,则不继续搜索
3. 若剩下的性价比最高的人的攻击次数不设限制且可以为小数,恰好打死boss的花费都比当前解差,则不继续搜索
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct Peo {
int h;
long long d,c;
friend bool operator < (const Peo &a,const Peo &b) {
if (a.d*b.c!=b.d*a.c) return a.d*b.c>b.d*a.c;
return a.c<b.c;
}
};
long long l;
Peo a[5];
long long maxdam[5];
long long cost,dam;
void dfs(int i,long long curcos,long long curdam) {
//printf("--%d %lld %lld\n",i,curcos,curdam);
if (curdam>=l) {
if (cost==-1||curcos<cost) {
cost=curcos;
dam=curdam;
} else if (curcos==cost&&curdam<dam) {
dam=curdam;
}
return;
}
if (i>=5) return;
if (maxdam[i]+curdam<l) return;
long long k=l-curdam;
k=k/a[i].d+(k%a[i].d!=0);
if (cost!=-1&&(k-1)*a[i].c+curcos>cost) return;
if (k>a[i].h) k=a[i].h;
for (int j=k;j>=0;j--) {
dfs(i+1,curcos+j*a[i].c,curdam+j*a[i].d);
}
}
int main() {
int t,i;
scanf("%d",&t);
while (t--) {
scanf("%lld",&l);
for (i=0;i<5;i++) scanf("%d%lld%lld",&a[i].h,&a[i].d,&a[i].c);
sort(a,a+5);
//for (i=0;i<5;i++) printf("%d %lld %lld\n",a[i].h,a[i].d,a[i].c);
maxdam[4]=a[4].d*a[4].h;
for (i=3;i>=0;i--) maxdam[i]=a[i].d*a[i].h+maxdam[i+1];
cost=-1;dam=-1;
dfs(0,0,0);
if (cost==-1) printf("We are doomed!!\n");
else printf("%lld %lld\n",cost,dam);
}
return 0;
}