题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4415
刚看见这个题目觉得很简单(其实不是),直接可以把整个集合分成两部分,一部分是有兵器的,一部分是没有兵器的
答案就是下面两种情况下最优的那个
第一种情况:只杀死所有没有兵器的敌人
第二种情况:有兵器的全部杀死,然后用得到的兵器和剩下的钱去杀没有兵器的那个集合,因为有兵器的这个集合只要能杀死一个,那么就全部都能杀死
当然这个题目没有那么简单,不能想当然的去直接用上面两种情况去做,当然第一种情况没什么好说的,关键是第二种情况,这里要小心,不能想当然去做
不过这里处理还是用的贪心思路
首先杀死有兵器的,肯定先用钱杀死有兵器中花费最小的那个,然后接着用兵器杀死整个有兵器的集合中的所有人,然后计算出当前获得的兵器数目去从
后向前(按照杀死需要的花费排序)去杀,完成之后开始用钱从前面开始杀,这里用钱杀不是真正意思上的用钱杀,意思是到花钱的时候了,现在假设要
杀没有兵器的a,那么用杀死a的花费和在有兵器集合里面用兵器杀掉的花费最小的那个花费比,如果小,那么直接用钱杀死,否则花钱换用兵器杀死的那
个人的兵器,也就是说本来用兵器杀死你的,现在我又不想了,那么用钱杀死你,换回杀死你的兵器去杀死价值更大的人,这时候这个兵器是不是用来杀
死a呢,当然可能不是了,要用这个换回来的兵器杀死无兵器集合里面当前没死的要杀死代价最大的那个人。
总之这个题目是一步步贪心下去,不能放过每一个最优的条件。
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
using namespace std;
#define maxn 110000
struct point
{
int a;
int b;
}first[maxn];
int second[maxn],num1,num2,n,m,ans1,money1,ans2,money2;
int cmp(const point &a,const point &b)
{
return a.a < b.a;
}
bool first_case()
{
int i,j,k,p=m,num,temp1,pos;
if(num1<=0 || first[0].a > m)
return false;
p-=first[0].a;
num=0;
for(i=0;i<num1;i++)
num+=first[i].b;
num-=num1;
num++;
ans1=num1;
money1=first[0].a;
if(num >= num2)
{
ans1+=num2;return true;
}
temp1=num2;
temp1-=num;
ans1+=num;
pos=1;
for(i=0;i<temp1 && (p>=first[pos].a || p>=second[i]); )
{
if( pos <num1 && first[pos].a <= second[i])
money1+=first[pos].a,temp1--,p-=first[pos].a,pos++;
else
money1+=second[i],p-=second[i],i++;
ans1++;
}
return true;
}
int second_case()
{
int i=0,j,k,p=m;
while(i< num2 && p>=second[i])
{
ans2++;
money2+=second[i];
p-=second[i];
i++;
}
//printf("%d %d\n",ans2,money2);
return 0;
}
int main()
{
int t,i,j,a,b,k=0;
scanf("%d",&t);
while(t--)
{
num1=num2=0;
ans1=ans2=0;
money1=money2=0;
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
{
scanf("%d%d",&a,&b);
if(b==0)
second[num2++]=a;
else
first[num1].a=a,first[num1++].b=b;
}
sort(first,first+num1,cmp);
sort(second,second+num2);
second_case();
if(first_case()==false)
{
printf("Case %d: %d %d\n",++k,ans2,money2);
continue;
}
if(ans1 > ans2)
{
printf("Case %d: %d %d\n",++k,ans1,money1);
}
else
{
if(ans1==ans2) printf("Case %d: %d %d\n",++k,ans1,money1 < money2 ? money1 : money2);
else
printf("Case %d: %d %d\n",++k,ans2,money2);
}
}
return 0;
}