Assassin’s Creed(hdu4415,贪心)

41 篇文章 0 订阅
10 篇文章 0 订阅

http://acm.hdu.edu.cn/showproblem.php?pid=4415

Assassin’s Creed

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

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

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

Sample Output

Case 1: 3 4 Case 2: 0 0

Source

2012 ACM/ICPC Asia Regional Hangzhou Online

Recommend

liuyiding

解析:

给出n个敌人和m的总能量

要消耗Ai能量可以杀死敌人并且获得可以杀掉Bi个敌人的能力,要求杀掉尽可能多的敌人,但是消耗的能量要最小。

思路:

两种情况:

1.尽力去杀死不含有敌方武器的的人

2.首先杀掉第一个含有地方武器(自己武器消耗也相对小的)求得总的敌方武器数为S+1

s+1>=n;毫无疑问可以杀死n个敌人,其中s个不需要消耗自己的武器

s+1<n:另外做考虑,可利用s个特权杀死消耗自己武器较大的敌人(因为此时是利用特权,不需消耗自己的武器)

然后利用自己剩余的武器来尽力杀死耗能小的敌人

在以上请境况下选择最优值

*/

#include<string.h
>#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<algorithm>
#include <iostream>
using namespace std;
const int maxn=100000+5;
int c1,c2,n1,n2;
int n,m;
int kill[maxn];
struct pt
{
 int a;
  int b;
}bt[maxn];
int cmp(pt x1,pt x2)
{
 return x1.a<x2.a;
}
void  work1()//一直砍没武器的
 { int t=m,i;
   for(i=1;i<=n;i++)
    if(!bt[i].b){
    if(t-bt[i].a>=0)
      {c1+=bt[i].a;
        t=t-bt[i].a;
          n1++;
       }
    else
      break;
      }
  }
void work2()//杀死含有敌方武器的优先考虑
 {
   int i;
   for(i=1;i<=n;i++)if(bt[i].b)break;//找到第一个含有敌方武器的
   if(i>=n+1)return ;//如果不存在含敌方武器则退出
   if(bt[i].a>m)return;//如果不可以杀死这个消耗自己武器,则说明不可行
   int t=i,s=0;//记入一下第一个含有敌方武器的坐标
   for(i=1;i<=n;i++)
   s+=bt[i].b;//可以获得敌方的武器总数
   if(s+1>=n)//利用这些武器可以杀死全部士兵,那么直接退出即可
      {
        n2=n;
        c2=bt[t].a;
        return ;
      }
   //如果不可以杀死n个人的要重新选择
   memset(kill,0,sizeof(kill));
      kill[t]=1;//将以杀死的标记为1
   n2=s+1;//当前最多可以杀死的人数
     i=n;
     while(s>0)//利用地方武器将消耗自己武器量大的先杀死
     {  if(!kill[i])//
         { s--;kill[i]=1;}
           i--;
         }
     c2=bt[t].a;
     for(i=1;i<=n;i++)//如果自己的武器无还有剩,则杀死较小消耗自己武器的敌人
     if(!kill[i])
      {if(m-bt[i].a-c2>=0)
        {
          n2++;
          c2+=bt[i].a;
        }
      }
 }
int main()
{
   int T,t;
  int i;
   scanf("%d",&T);
   for(t=1;t<=T;t++)
   {
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)
       scanf("%d%d",&bt[i].a,&bt[i].b);
      sort(bt+1,bt+n+1,cmp);//注意这里的下标是从1开始的
  c1=c2=n1=n2=0;
  work1();
  work2();
  printf("Case %d: ",t);
 if(n1>n2||(n1==n2&&c1<c2))
  printf("%d %d\n",n1,c1) ;
else
  printf("%d %d\n",n2,c2);
   } 
return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值