Question link:
Http://acm.hdu.edu.cn/showproblem.php? PID = 1, 4415
Question meaning:
To kill n enemies, each of them has two attributes: A and B. A indicates the required capacity to kill him. B indicates that after killing him, you can kill another enemy for free. Tell the initial capability value to find the most killer enemies and the minimum cost of killing so many enemies.
Solution:
Classification + greedy
This question is difficult and classic. Good question.
First, divide the enemy into two types: A and B based on whether the value of B is zero. Class A indicates that the value of B is not zero, and Class B indicates that the value of B is zero. A and B are sorted by a in ascending order.
First, it is clear:
1. If you want to kill Class A, at least a [0]. A capability value is required. You can kill all Class A, and there are more free places to kill Class B.
2. If you can kill Class A [0]. A, no matter whether you want to kill Class A or use free places to kill Class A, the total number of free places to kill Class B remains unchanged.
Consider three situations:
1. Try to kill Class B as much as possible, and then check whether the remaining capabilities can kill Class A with the smallest a value in Class A [0], then kill all Class A, and then kill Class B with a free quota.
2. First kill a [0], then kill all Class A, then kill Class B with more free places, and then kill Class B with more costs.
3. Kill Class A [0] first. In this case, instead of killing Class A with a free quota, it compares Class A and Class B which have a smaller value, then, we may use the spending capacity value to kill Class A and the extra free quota to kill Class B.
5 4
1 1
2 2
3 0
4 0
5 0
Answer:5 3 if you want to kill Class A at least 1 and can kill Class A, Class A can certainly be completely killed. In this case, the free quota is 2 (excluding the cost of A), and the cost is used to kill 2 2 of Class, this avoids spending more capacity values to kill Class B with a larger a value.
The code is explained in detail.
// # Include <cspreadsheet. h> # include <iostream> # include <cmath> # include <cstdio> # include <sstream> # include <cstdlib> # 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 # 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 indicates selecting Class A num2, and cost2 indicates selecting class B INT I = 0, j = 0, P = B. size ()-1; // P indicates the last element of Class B // printf ("P: % d \ n", P); While (I <B. size () & m-cost2> = B [I]. a) // select class B as much as possible {cost2 + = B [I]. a; num2 ++; I ++;} I = 0; if (I <. size () & M> = A [I]. a) // select class A from the beginning, and select class B if there are more {num1 + =. size (); cost1 = A [I]. a; while (I <. size () sum + = A [I ++]. b; sum-=. size ()-1;} I = 0; if (I <. size () & m-cost2> = A [I]. a) // After selecting B, select class A to see if all Class A can be completed {num2 + =. size (); cost2 + = A [I]. a; num2 + = sum; // If the row is selected, you can definitely select sum. // so far, if you select class B first, all the cases are completed. If (num2> N) num2 = n ;}while (P >=0 & sum) p --, sum --, num1 ++; // select class A first and then Class B, it is also possible to continue the payment to select class B if (p <0) // indicates that Class A is selected first, if you select class B again, you do not need to spend any time to complete Class B. Note that if you want to eliminate Class A, at least a [0] is required. 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"); // consider whether the Class A is free or cost-effective, then the extra one is free to engage in Class B for (I = 1, j = 0; j <= P & I <. size () & m-cost1> = min (A [I]. a, B [J]. a);) {if (a [I]. A <= B [J]. a) // select the cost to eliminate the current Class A and create a class B. {// note that the total volume remains unchanged. cost1 + = A [I]. a; p --; I ++; num1 ++;} else // use the cost to eliminate Class 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", & N, & M);. clear (); B. clear (); For (INT I = 1; I <= N; I ++) {INF temp; scanf ("% d", & temp. a, & temp. b); If (temp. b). push_back (temp); else B. push_back (temp);} Sort (. begin (),. end (), CMP); sort (B. begin (), B. end (), CMP); int num, cost; CAL (Num, cost); printf ("case % d: % d \ n", ++ kcas, num, cost);} return 0;}/* 5 41 12 23 05 06 0 keys: 5 3 */
[Greedy] HDU 4415 Assassin's Creed