[贪心] hdu 4415 Assassin’s Creed

题目链接:

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

题目意思: 

要杀死n个敌人,每个敌人有两个属性a和b,a表示杀他所需要的能力值,b表示杀掉他后可以免费再杀b个敌人。告诉初始能力值,求能杀的最多的敌人,及杀掉那么多敌人的最小花费。

解题思路:

分类+贪心

这道题比较难,也比较经典。好题。

首先把敌人按b值是否为零分成两类A和B。A类表示b值不为零,B类表示b值为零。A、B分别按a从小到大排序

首先明确:

1、如果要杀A类,至少需要A[0].a能力值,并且可以把A类全部杀掉,而且还有多的免费名额可以再杀B类。

2、如果能杀A[0].a,则无论是花费杀A类,还是用免费名额杀A类,总的得到的杀B类的免费名额是不变的。

考虑三种情况:

1、先尽可能的杀B类,然后剩余的能力看能不能杀掉A中a值最小的A[0],然后把A类全部杀掉,再用免费的名额杀B。

2、先杀A[0],然后把A类全部杀掉,然后多的免费名额再杀B类,然后用多的花费来杀B类。

3、先杀A[0],此时不是用免费名额杀A类,而是比较A类和B类哪个a值较小,然后可能用花费能力值来杀A类,多出的那个免费名额来杀B类。

5 4

1 1

2 2

3 0

4 0

5 0

答案:5 3   如果要杀A类,至少要花费1,并且能杀A类的话,A类肯定可以全部杀完。此时得到的免费名额都是2(除开A的花销),而此时选择用花费来杀掉A类的2 2,这样就避免了花费更多的能力值去杀a值比较大的B类。

代码解释的很详细。

//#include<CSpreadSheet.h>

#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<ctime>
#include<bitset>
#include<cmath>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define ll __int64
#define LL long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#define M 1000000007
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

struct Inf
{
    int a,b;
};
vector<Inf>A,B;
int n,m;

bool cmp(Inf aa,Inf bb)
{
    return aa.a<bb.a;
}

void cal(int &num,int &cost)
{
    int num1=0,cost1=0,num2=0,cost2=0,sum=0;  //num1,cost1表示先选A类 num2,cost2表示先尽可能的选B类
    int i=0,j=0,p=B.size()-1; //p表示B类的最后一个元素

    //printf("p:%d\n",p);

    while(i<B.size()&&m-cost2>=B[i].a) //先尽可能的选B类
    {
        cost2+=B[i].a;
        num2++;
        i++;
    }
    i=0;
    if(i<A.size()&&m>=A[i].a) //一开始就选A类,多的再选B类
    {
        num1+=A.size();
        cost1=A[i].a;
        while(i<A.size())
            sum+=A[i++].b;
        sum-=A.size()-1;
    }
    i=0;
    if(i<A.size()&&m-cost2>=A[i].a) //把B选完后,再选A类看能不能把A类全部搞完
    {
        num2+=A.size();
        cost2+=A[i].a;
        num2+=sum;  //如果行,一定可以选sum个  //至此先选B类的情况已经全部算完了
        if(num2>n)
            num2=n;
    }
    while(p>=0&&sum)
        p--,sum--,num1++;  //先选A类,再选B类的情况,还有可能继续支付花费来选B类
    if(p<0) //说明先选A类,再选B类的情况可以不用花费就把B类全搞定  注意如果要消灭A类,至少要花费A[0].a
    {
        if((num1>num2)||(num1==num2&&cost1<cost2))
            num=num1,cost=cost1;
        else
            num=num2,cost=cost2;
        return ;
    }
    //printf("num1:%d cost1:%d num2:%d cost2:%d sum:%d p:%d\n",num1,cost1,num2,cost2,sum,p);
    //system("pause");

    //再考虑A类中,是考虑用免费的,还是用花费的,然后多出来的那个免费去搞B类
    for(i=1,j=0;j<=p&&i<A.size()&&m-cost1>=min(A[i].a,B[j].a);)
    {
        if(A[i].a<=B[j].a) //选择花费来消灭当前这个A类,同时腾出来一个消灭B类
        {                  //注意总的量不变
            cost1+=A[i].a;
            p--;
            i++;
            num1++;

        }
        else     //用花费来消灭B类
        {
            cost1+=B[j].a;
            j++;
            num1++;

        }
    }
    //printf("::cost1:%d p:%d\n",cost1,p);
    while(j<=p)
    {
        if(m-cost1>=B[j].a)
        {
            num1++;
            cost1+=B[j].a;
            j++;
        }
        else
            break;

    }
    //printf("num1:%d cost1:%d num2:%d cost2:%d sum:%d p:%d\n",num1,cost1,num2,cost2,sum,p);
    //system("pause");

    if((num1>num2)||(num1==num2&&cost1<cost2))
        num=num1,cost=cost1;
    else
        num=num2,cost=cost2;
    return ;
}

int main()
{
    //freopen("in.txt","r",stdin);
   //freopen("out.txt","w",stdout);
   int t,kcas=0;

   scanf("%d",&t);
   while(t--)
   {
       scanf("%d%d",&n,&m);
       A.clear();
       B.clear();

       for(int i=1;i<=n;i++)
       {
           Inf temp;
           scanf("%d%d",&temp.a,&temp.b);
           if(temp.b)
                A.push_back(temp);
           else
                B.push_back(temp);
       }
       sort(A.begin(),A.end(),cmp);
       sort(B.begin(),B.end(),cmp);
       int num,cost;
       cal(num,cost);

       printf("Case %d: %d %d\n",++kcas,num,cost);
   }
    return 0;
}
/*
5 4
1 1
2 2
3 0
5 0
6 0

keys:5 3
*/
时间: 2024-11-05 03:29:44

[贪心] hdu 4415 Assassin’s Creed的相关文章

HDU 4415 Assassin’s Creed

实在难想,贪心.别人的思路:点击打开链接 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 enem

HDU 4415 Assassin&amp;#39;s Creed(贪心)

pid=4415">HDU 4415 题意: 壮哉我Assassin! E叔有一柄耐久度为m的袖剑,以及n个目标士兵要去解决. 每解决掉一个士兵,消耗袖剑Ai的耐久度.且获得该士兵的武器,能够使用该武器解决Bi名其它士兵. E叔要尽可能地消耗更少耐久度解决很多其它的敌人,求最小消耗与最大杀敌数. 思路: 我们把士兵分为两个集合:e1与e2.e1的士兵 Bi = 0 . e2 的 Bi > 0. 我们发现.假设能解决e2的随意一个,e2就可以全灭,那么我们对e2依据消耗进行升序排序,消

贪心/hdu 1009 FatMouse&#39; Trade

题意 有n种物品,每一种需要不同的消费,现在手里有m块钱,求问最多可以买多少 分析 贪心 把每一种物品的价格算出来,然后sort一下,按照价格从便宜到贵排序,能买多少买多少,买买买! Accepted Code 1 /* 2 PROBLEM:hdu1009 3 AUTHER:Nicole Lam 4 MEMO:贪心 5 */ 6 7 #include<cstdio> 8 #include<algorithm> 9 using namespace std; 10 11 12 stru

贪心 --- hdu : Road Trip

Road Trip Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:65536KB Total submit users: 29, Accepted users: 29 Problem 12882 : No special judgement Problem description You are planning a road trip to visit your friends, each of whom live in

Light OJ 1406 Assassin`s Creed 状态压缩DP+强连通缩点+最小路径覆盖

题目来源:Light OJ 1406 Assassin`s Creed 题意:有向图 派出最少的人经过全部的城市 而且每一个人不能走别人走过的地方 思路:最少的的人能够走全然图 明显是最小路径覆盖问题 这里可能有环 所以要缩点 可是看例子又发现 一个强连通分量可能要拆分 n最大才15 所以就状态压缩 将全图分成一个个子状态 每一个子状态缩点 求最小路径覆盖 这样就攻克了一个强连通分量拆分的问题 最后状态压缩DP求解最优值 #include <cstdio> #include <cstri

Light OJ 1429 Assassin`s Creed (II) BFS+缩点+最小路径覆盖

题目来源:Light OJ 1429 Assassin`s Creed (II) 题意:最少几个人走完全图 可以重复走 有向图 思路:如果是DAG图并且每个点不能重复走 那么就是裸的最小路径覆盖 现在不是DAG 可能有环 并且每个点可能重复走 对于有环 可以缩点 缩点之后的图是DAG图 另外点可以重复走和POJ 2594一样 先预处理连通性 #include <cstdio> #include <cstring> #include <vector> #include &

[游戏分析]刺客信条:兄弟会(Assassin&#39;s&#160;Creed:&#160;Brotherhood)

1 机制 1.1 界面与按键 1.1.1 在主菜单进行功能选择时,画面右下角会伴有按键提示字幕,如{Enter}选择(按Enter键即选择当前指定的功能).{Backspace}返回等. 1.1.2 在游戏进行过程中,画面右上方始终会显示一套按键组合,该组合包含4个{按键}+提示文字的配对.组合内的各个{按键}+提示文字配对会因主角所处场景(行走.攀爬.战斗等)的不同作出对应的变化,以保证玩家在不同场景下都可以迅速了解自己可选择的最基本的操作方法. 1.2 教程 1.2.1 简要介绍前两部的剧情

ACM学习历程—HDU4415 Assassin’s Creed(贪心)

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

(贪心) hdu 3183

A Magic Lamp Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1858    Accepted Submission(s): 727 Problem Description Kiki likes traveling. One day she finds a magic lamp, unfortunately the genie