HDU 4415 Assassin’s Creed(贪心)

题目链接: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
  1 #include <iostream>

  2 #include <cstdio>

  3 #include <cstring>

  4 #include <vector>

  5 #include <algorithm>

  6 #define min(x,y) ((x)<(y)?(x):(y))

  7 #define max(x,y) ((x)>(y)?(x):(y))

  8 using namespace std;

  9 

 10 struct node

 11 {

 12     int a,b;

 13 

 14     node(){}

 15     node(int _a,int _b)

 16     {

 17         a=_a;

 18         b=_b;

 19     }

 20 };

 21 

 22 const int INF=1000000005;

 23 const int MAX=100005;

 24 vector<node> A,B;

 25 int n,m,num=0;

 26 int C;

 27 

 28 int cmp(node a,node b)

 29 {

 30     return a.a<b.a;

 31 }

 32 

 33 void cal(int &Num,int &Cost)

 34 {

 35     int cost1=0,cost2=0,num1=0,num2=0,sum=0,p=B.size()-1,i,j;

 36 

 37 

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

 39     {

 40         num1++;

 41         cost1+=B[i].a;

 42     }

 43 

 44     if(A.size()&&A[0].a<=m)

 45     {

 46         cost2+=A[0].a;

 47         num2=A.size();

 48         for(i=0;i<A.size();i++) sum+=A[i].b;

 49         sum-=(A.size()-1);

 50     }

 51 

 52     if(A.size()&&A[0].a<=m-cost1)

 53     {

 54         cost1+=A[0].a;

 55         num1+=A.size();

 56         num1+=sum;

 57         if(num1>n) num1=n;

 58     }

 59 

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

 61 

 62     if(p<0)

 63     {

 64         if(num2>num1||num2==num1&&cost2<cost1)

 65         {

 66             Num=num2;

 67             Cost=cost2;

 68         }

 69         else

 70         {

 71             Num=num1;

 72             Cost=cost1;

 73         }

 74         return;

 75     }

 76     for(i=1,j=0;i<A.size()&&j<=p&&m-cost2>=min(A[i].a,B[j].a);)

 77     {

 78         if(A[i].a<=B[j].a)

 79         {

 80             cost2+=A[i].a;

 81             num2++;

 82             p--;

 83             i++;

 84         }

 85         else

 86         {

 87             cost2+=B[j].a;

 88             num2++;

 89             j++;

 90         }

 91     }

 92     while(j<=p)

 93     {

 94         if(m-cost2>=B[j].a)

 95         {

 96             cost2+=B[j].a;

 97             num2++;

 98             j++;

 99         }

100         else break;

101         j++;

102     }

103     if(num2>num1||num2==num1&&cost2<cost1)

104     {

105         Num=num2;

106         Cost=cost2;

107     }

108     else

109     {

110         Num=num1;

111         Cost=cost1;

112     }

113 }

114 

115 int main()

116 {

117     for(scanf("%d",&C);C--;)

118     {

119         A.clear();

120         B.clear();

121         scanf("%d%d",&n,&m);

122         int i;

123         node p;

124         for(i=1;i<=n;i++)

125         {

126             scanf("%d%d",&p.a,&p.b);

127             if(p.b) A.push_back(p);

128             else B.push_back(p);

129         }

130         sort(A.begin(),A.end(),cmp);

131         sort(B.begin(),B.end(),cmp);

132         int Num,Cost;

133         cal(Num,Cost);

134         printf("Case %d: ",++num);

135         printf("%d %d\n",Num,Cost);

136     }

137     return 0;

138 }

 

 

你可能感兴趣的:(sass)