HDU 4381 Grid [背包DP]

  1~N连续的白格子,给出若干操作,分为两种,在[1,ai]里选择xi个白格子染成黑色,以及在[ai,n]里选择xi个白格子染成黑色。问把最多的格子染成黑色至少需要多少次操作。

  先只考虑第一种操作,显然优先把最左边的填满,对于第二种操作,优先把最右边的填满。这就转化成了背包模型,做完两遍后合并背包即可。

 1 #include <string.h>
 2 #include <stdio.h>
 3 #include <algorithm>
 4 #define INF 0x3f3f3f3f
 5 #define MAXN 1005
 6 using namespace std;
 7 struct oper{
 8     int op, ai, xi;
 9     bool operator <(const oper& o) const {
10         return op < o.op || (op == o.op && ai < o.ai);
11     }
12 }p[MAXN];
13 int cas, n, m, op[2], tx, ty, tz;
14 int d1[MAXN], d2[MAXN];
15 int main(){
16     scanf("%d", &cas);
17     for (int ca = 1; ca <= cas; ca++) {
18         scanf("%d%d", &n, &m);
19         op[0] = op[1] = 0;
20         for (int i = 0; i < m; i++) {
21             scanf("%d%d%d", &tx, &ty, &tz);
22             p[i].op = tx, p[i].ai = ty, p[i].xi = tz;
23             op[tx-1]++;
24         }
25         std::sort(p, p + m);
26         memset(d1, 0x3f, sizeof d1); d1[0] = 0;
27         memset(d2, 0x3f, sizeof d2); d2[0] = 0;
28         for (int i = 0; i < op[0]; i++)
29             for (int j = p[i].ai - p[i].xi; j >= 0; j--)
30                 if(d1[j]!=INF) d1[j+p[i].xi] = min(d1[j+p[i].xi], d1[j]+1);
31         for (int i = m-1; i >= op[0]; i--)
32             for (int j = n - p[i].ai - p[i].xi+1; j >= 0; j--)
33                 if(d2[j]!=INF) d2[j+p[i].xi] = min(d2[j+p[i].xi], d2[j]+1);
34         int ans1 = 0, ans2 = 0;
35         for (int i = 0; i <= n; i++)
36             for (int j = n-i; j >=0; j--)
37                 if(d1[i]!=INF&&d2[j]!=INF&&(i+j>ans1||i+j==ans1&&d1[i]+d2[j]<ans2)) ans1 = i+j, ans2 = d1[i]+d2[j];
38 
39         printf("Case %d: %d %d\n", ca, ans1, ans2);
40     }
41     return 0;
42 }
原文地址:https://www.cnblogs.com/swm8023/p/2710688.html