HDU 4415 Assassin’s Creed

题意: 一个人有一把剑,剑有一个耐久度m,现在有n个敌人,每个敌人都对应一个ai值和bi值,ai表示

         杀掉这个敌人需要消耗ai的的武器耐久度,同时可以获得他的剑并且可以用他的剑杀死bi个敌人,

         问最多可以杀掉多少个敌人。

分析: 有两种情况:

          ①只杀 bi为 0 的; 

          ②杀了某个bi不为 0 的敌人,那么所有bi不为 0 的最后都会被杀掉,           

            这种情况只要枚举多少个bi不为0 的敌人是花自己的耐久度去杀的,找一个最优解

          要让用耐久度杀的敌人消耗的耐久度尽可能小,需要实现按照ai排序,找ai最小的每次。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 100005
#define INF 0x1f1f1f1f
struct node
{
    int ai,bi;
}vb[maxn],vnob[maxn],tmp;
// bi不为0的集合,bi为0的集合
bool cmp(node a,node b)
{
    return a.ai<b.ai;
}
int main()
{
    int t,n,i,j,ca=1,m;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        int sumb=0;
        int vb_top=0,nob_top=0;
        for(i=1;i<=n;i++)
        {
            scanf("%d%d",&tmp.ai,&tmp.bi);
            if(tmp.bi)
            {
                sumb+=tmp.bi;           // 统计可以获得的敌人的武器数
                vb[vb_top++]=tmp;       // bi 不为 0 的
            }
            else vnob[nob_top++]=tmp;   // bi 为 0 的
        }

        sort(vb,vb+vb_top,cmp);       
        sort(vnob,vnob+nob_top,cmp);
        int ansn=0,ansd=0,sum=0;
        int ta=0,td=0,fr=0;
        int tm=m;
        for(i=0;i<nob_top;i++)          // 只杀bi为0的集合的情况
        {
            if(vnob[i].ai<=tm)
            {
                tm-=vnob[i].ai;
                td+=vnob[i].ai;
                ta++;
            }
            else break;
        }
        ansn=ta;
        ansd=td;
        for(i=0;i<vb_top;i++)  // bi 不为0 的集合中只要一个被消灭,其他的都会被消灭
        {                      // 这里枚举用自己的武器杀的bi非0集合中的人数
            sum+=vb[i].ai;       
            if(sum>m)          // sum: 用自己的武器消灭 (i+1)个 bi非0集合中人消耗的耐久度
                break;
            tm=m-sum;          // tm:  消灭(i+1)个bi非0集合中人之后剩下的耐久度,这些将拿来消灭
                               //      bi 为0 集合中ai值比较小的那些人
            td=sum;            // td:  当前消耗的耐久度
            ta=vb_top; 
            fr=sumb-vb_top+i+1; // fr:  消灭完bi非0集合中的敌人后剩下的敌人的武器数
            ta+=min(nob_top,fr);//      剩下的武器数如果大于bi为0集合中的人数,那么就直接灭完了
            for(j=0;j<nob_top-fr;j++)// 用剩下的敌人的武器消灭bi为0集合中的人时尽量消灭ai大的 
            {                        
                if(vnob[j].ai<=tm)   // 用剩下的耐久度尽量消灭bi为0集合中ai小的
                {
                    tm-=vnob[j].ai;
                    td+=vnob[j].ai;
                    ta++;
                }
                else break;
            }
            if(ta>ansn)
            {
                ansn=ta;
                ansd=td;
            }
            else if(ta==ansn&&td<ansd)
                ansd=td;
        }
            printf("Case %d: %d %d\n",ca++,ansn,ansd);
    }
    return 0;
}

 

 

 

posted @ 2012-09-24 20:46  'wind  阅读(1461)  评论(0编辑  收藏  举报