题目链接:
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3474
题解:
题意:
一个人要打跆拳道,他要打n个人,并且知道他的初始的能量m,然后n行,每行有m1,m2,m3 以及s,前面的三个表示打这个部位会消耗的能量,并且打m1会得到三分,打m2会得到2分,打m3只会得到一分,并且知道打到一个人需要7分,打倒这个人之后,你会得到s点能量,问你最后打到全部人之后剩余的最多的能量,如果不能打倒全部的人,就输出-1。
我们首先需要知道打到一个人需要消耗的最小的能量,这个最小能量可以直接去暴力求解,枚举7的由1,2,3可以组成的所有的情况,然后去取个最小的。难点是怎么能够判断能够打倒所有的人,这里可以使用贪心的方法,但是需要注意的是,我们在考虑的是怎么能够打倒所有的人,而不是打人需要的需要消耗的少的时间。
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define met(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
const int maxn = 100+10;
struct node
{
int cost;
int get;
}a[maxn],b[maxn];
int cmp1(node a,node b)
{
return a.cost<=b.cost;
}
int cmp2(node a,node b)
{
return a.get>=b.get;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
int len1=0;
int len2=0;
met(a,0);
met(b,0);
for(int i=0;i<n;i++)
{
int x,y,z,get;
scanf("%d%d%d%d",&x,&y,&z,&get);
int cost=inf;
for(int k=0; k<=4; k++)
for(int kk=0; kk<=4; kk++)
for(int kkk=0; kkk<=8; kkk++) {
int res=k*3+2*kk+kkk;
if(res>=7)
cost=min(cost,k*x+kk*y+kkk*z);
}
// cout<<get<<endl;
if(get>cost)
{
a[len1].cost=cost;
a[len1].get=get;
len1++;
}
else
{
b[len2].cost=cost;
b[len2].get=get;
len2++;
}
}
sort(a,a+len1,cmp1);
sort(b,b+len2,cmp2);
int flag=0;
for(int i=0;i<len1;i++)
{
if(m<=a[i].cost)
{
flag=1;
break;
}
m+=a[i].get-a[i].cost;
}
if(flag)
{
printf("no\n");
continue;
}
flag=0;
for(int i=0;i<len2;i++)
{
if(m<=b[i].cost)
{
flag=1;
break;
}
m+=b[i].get-b[i].cost;
}
if(flag)
printf("no\n");
else
printf("%d\n",m);
}
}