您的位置:首页 > 其它

HDU 4415 Assassin’s Creed(贪心)

2012-10-04 14:35 302 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4415

题意:一个杀手,有m的攻击力,n个敌人。每个敌人有两个属性ai,bi,表示杀死这个敌人需要ai的攻击力,杀死该敌人后,

可以再免费杀死bi个其他的敌人而不花费自己的攻击力。求最多可以杀死多少个敌人?在此基础上花费的最少的攻击力是多少?

思路:将所有的敌人分为两类A和B,A是bi值不为0的,B是bi值为0的:

(1)优先杀B类的:用攻击力杀掉尽可能多的B类的,剩余的攻击力若还能杀A类的某一个,则显然,必能将A类得全部干掉,

并且还可能有一些可以免费的还可以再接着杀掉B的一些;

6 5

1 0

1 0

1 0

1 0

1 0

5 1

像这组数据,显然优先杀掉B类的是最划算的。。。。

(2)优先杀掉A类的:由于A类的你能干掉其中一个,就可以将A类全部干掉,而且还可以有剩余的免费的还能接着干掉B类的,若攻击力还有,

还可以接着杀掉B类得一些,比如这组数据:

6 1

1 5

1 0

1 0

1 0

1 0

1 0

你发现干掉A中的一个后可以用免费的将B类全部干完。这样貌似问题就解决了,但是还有这种情况:

5 7
3 2
4 1
5 0
6 0
7 0

这组数据的答案是5 7.首先用7的攻击力将A类的干掉,用干掉A类得到的3的免费的将B类干掉,也就是说,A类的一些不一定

用干掉A的第一个后得到的免费名额。这样的话,首先干掉A类ai值最小的,然后将A类剩余的和B类的一起考虑,每次用自己的攻击力干掉其中

ai值最小的。

View Code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#define min(x,y) ((x)<(y)?(x):(y))
#define max(x,y) ((x)>(y)?(x):(y))
using namespace std;

struct node
{
int a,b;

node(){}
node(int _a,int _b)
{
a=_a;
b=_b;
}
};

const int INF=1000000005;
const int MAX=100005;
vector<node> A,B;
int n,m,num=0;
int C;

int cmp(node a,node b)
{
return a.a<b.a;
}

void cal(int &Num,int &Cost)
{
int cost1=0,cost2=0,num1=0,num2=0,sum=0,p=B.size()-1,i,j;

for(i=0;i<B.size();i++) if(m-cost1>=B[i].a)
{
num1++;
cost1+=B[i].a;
}

if(A.size()&&A[0].a<=m)
{
cost2+=A[0].a;
num2=A.size();
for(i=0;i<A.size();i++) sum+=A[i].b;
sum-=(A.size()-1);
}

if(A.size()&&A[0].a<=m-cost1)
{
cost1+=A[0].a;
num1+=A.size();
num1+=sum;
if(num1>n) num1=n;
}

while(sum>0&&p>=0) sum--,p--,num2++;

if(p<0)
{
if(num2>num1||num2==num1&&cost2<cost1)
{
Num=num2;
Cost=cost2;
}
else
{
Num=num1;
Cost=cost1;
}
return;
}
for(i=1,j=0;i<A.size()&&j<=p&&m-cost2>=min(A[i].a,B[j].a);)
{
if(A[i].a<=B[j].a)
{
cost2+=A[i].a;
num2++;
p--;
i++;
}
else
{
cost2+=B[j].a;
num2++;
j++;
}
}
while(j<=p)
{
if(m-cost2>=B[j].a)
{
cost2+=B[j].a;
num2++;
j++;
}
else break;
j++;
}
if(num2>num1||num2==num1&&cost2<cost1)
{
Num=num2;
Cost=cost2;
}
else
{
Num=num1;
Cost=cost1;
}
}

int main()
{
for(scanf("%d",&C);C--;)
{
A.clear();
B.clear();
scanf("%d%d",&n,&m);
int i;
node p;
for(i=1;i<=n;i++)
{
scanf("%d%d",&p.a,&p.b);
if(p.b) A.push_back(p);
else B.push_back(p);
}
sort(A.begin(),A.end(),cmp);
sort(B.begin(),B.end(),cmp);
int Num,Cost;
cal(Num,Cost);
printf("Case %d: ",++num);
printf("%d %d\n",Num,Cost);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: