hdu 4381(背包问题)
题意:有一排箱子全是黑色的,然后有两种操作1 a x从1-a跳出x个变成白色。2 a x从a-x跳出x个变成白色。要你求最多能变成白色的个数和最少的操作数。
思路:转化成背包问题,把两种操作分开进行背包,最后两重循环枚举找最优解即可。
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /************************************************** 2 * Author : xiaohao Z 3 * Blog : http://www.cnblogs.com/shu-xiaohao/ 4 * Last modified : 2014-03-29 15:45 5 * Filename : MulSchool.cpp 6 * Description : 7 * ************************************************/ 8 9 #include <iostream> 10 #include <cstdio> 11 #include <cstring> 12 #include <cstdlib> 13 #include <cmath> 14 #include <algorithm> 15 #include <queue> 16 #include <stack> 17 #include <vector> 18 #include <set> 19 #include <map> 20 #define MP(a, b) make_pair(a, b) 21 #define PB(a) push_back(a) 22 23 using namespace std; 24 typedef long long ll; 25 typedef pair<int, int> pii; 26 typedef pair<unsigned int,unsigned int> puu; 27 typedef pair<int, double> pid; 28 typedef pair<ll, int> pli; 29 typedef pair<int, ll> pil; 30 31 const int INF = 0x3f3f3f3f; 32 const double eps = 1E-6; 33 const int LEN = 100000+10; 34 int T, n, m, ta, tb, dp1[LEN], dp2[LEN]; 35 struct OP{ 36 int pos, x; 37 }; 38 OP op1[LEN], op2[LEN]; 39 40 bool cmp1(OP a, OP b){ 41 if(a.pos != b.pos) return a.pos < b.pos; 42 else a.x < b.x; 43 } 44 45 bool cmp2(OP a, OP b){ 46 if(a.pos != b.pos) return a.pos > b.pos; 47 else a.x < b.x; 48 } 49 50 int main() 51 { 52 // freopen("in.txt", "r", stdin); 53 54 int kase = 1; 55 scanf("%d", &T); 56 while(T--){ 57 scanf("%d%d", &n, &m); 58 ta = tb = 0; 59 memset(dp1, 0x3f, sizeof dp1); 60 memset(dp2, 0x3f, sizeof dp2); 61 for(int i=0; i<m; i++){ 62 int op = 0, a, b; 63 scanf("%d%d%d", &op, &a, &b); 64 if(op == 1) { 65 op1[ta].pos = a; 66 op1[ta].x = b; 67 ta++; 68 }else{ 69 op2[tb].pos = a; 70 op2[tb].x = b; 71 tb++; 72 } 73 } 74 sort(op1, op1+ta, cmp1); 75 sort(op2, op2+tb, cmp2); 76 dp1[0] = dp2[n+1] = 0; 77 for(int j=0; j<ta; j++){ 78 for(int i=n; i>=0; i--){ 79 if(op1[j].pos >= i && i - op1[j].x >= 0 && dp1[i - op1[j].x] != INF){ 80 dp1[i] = min(dp1[i], dp1[i - op1[j].x]+1); 81 } 82 } 83 } 84 for(int j=0; j<tb; j++){ 85 for(int i=1; i<=n+1; i++){ 86 if(op2[j].pos <= i && i + op2[j].x <= n+1 && dp2[i + op2[j].x] != INF){ 87 dp2[i] = min(dp2[i], dp2[i + op2[j].x]+1); 88 } 89 } 90 } 91 int ansa = INF, ansb = INF; 92 for(int i=0; i<=n; i++){ 93 for(int j=i+1; j<=n+1; j++){ 94 if(dp1[i] != INF && dp2[j] != INF){ 95 if(j-i-1 < ansa){ 96 ansa = j-i-1; 97 ansb = dp1[i] + dp2[j]; 98 } 99 if(j-i-1 == ansa){ 100 ansb = min(dp1[i] + dp2[j], ansb); 101 } 102 } 103 } 104 } 105 if(ansb == INF) ansb = 0; 106 printf("Case %d: %d %d\n", kase++, n-ansa, ansb); 107 } 108 return 0; 109 }
奔跑吧!少年!趁着你还年轻