hdu4415(贪心)

来源:互联网 发布:linux top命令进程状态 编辑:程序博客网 时间:2024/05/21 06:46

Assassin’s Creed

Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1332    Accepted Submission(s): 344


Problem Description
Ezio Auditore is a great master as an assassin. Now he has prowled in the enemies’ base successfully. He finds that the only weapon he can use is his cuff sword and the sword has durability m. There are n enemies he wants to kill and killing each enemy needs Ai durability. Every time Ezio kills an enemy he can use the enemy’s sword to kill any other Bi enemies without wasting his cuff sword’s durability. Then the enemy’s sword will break. As a master, Ezio always want to do things perfectly. He decides to kill as many enemies as he can using the minimum durability cost.
 

Input
The first line contains an integer T, the number of test cases.
For each test case:
The first line contains two integers, above mentioned n and m (1<=n<=10^5, 1<=m<=10^9).
Next n lines, each line contains two integers Ai, Bi. (0<=Ai<=10^9, 0<=Bi<=10).
 

Output
For each case, output "Case X: " (X is the case number starting from 1) followed by the number of the enemies Ezio can kill and the minimum durability cost.
 

Sample Input
23 54 15 17 72 12 24 0
 

Sample Output
Case 1: 3 4Case 2: 0 0
 

Source
2012 ACM/ICPC Asia Regional Hangzhou Online
 

Recommend
liuyiding
        本题要求在费持久性尽可能少的情况下保证杀敌最多,其中有的敌人可以杀死某一数量的其他敌人。
        根据题意和n的数量级,易知本题是个贪心问题。我们应该选择合适的贪心策略。
贪心策略:
         1.若能杀死一个带剑的敌人,就杀死他,统计所有可以间接杀死的敌人的总数。然后杀掉剩余费持久值最大的敌人。
         2.用剩下的持久值从小到大杀死其他的敌人。
看了其他人的结题报告,发现这个确实有不符合逻辑的地方,但却过了!
#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>using namespace std;const int MAXN=100000+100;struct node{int dura, kil;}Per[MAXN];bool visited[MAXN];//标识该人是否已被杀int ans,sum,n,m;bool cmp(node a,node b){return a.dura<b.dura;}void Solve(){int i,id,tmp,free=m;memset(visited,0,sizeof(visited));for(i=0;i<n;i++)//标识第一个可以继续杀敌人的敌人{if(Per[i].kil)break;}id=i;sum=0;if(id>=n||free<Per[id].dura)return;//不能杀死任何人for(i=id;i<n;i++)//统计累计可以相互杀死的人的个数{sum+=Per[i].kil;}if(sum+1>=n)//相互杀即可杀光所有的人{ans=free-Per[id].dura;sum=n;return ;}i=n-1;visited[id]=true;tmp=sum;while(sum>0&&i>=0)//从大到小依次杀死可以不用钱杀的人{if(!visited[i]){visited[i]=true;sum--;}i--;}ans=free-Per[id].dura;sum=tmp+1;for(i=0;i<n;i++)//剩余的用钱杀{if(!visited[i]&&ans>=Per[i].dura){ans-=Per[i].dura;sum++;}else if(ans<Per[i].dura)return ;}}int main(){int cas,i,tag=1;cin>>cas;while(cas--){scanf("%d%d",&n,&m);for(i=0;i<n;i++){scanf("%d%d",&Per[i].dura,&Per[i].kil);}sort(Per,Per+n,cmp);Solve();printf("Case %d: ",tag++);printf("%d %d\n",sum,m-ans);}return 0;}

原创粉丝点击