题目链接: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值最小的。
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 }