CF 1013E Hills

这是一道DP题...我居然有那么半个小时思考非DP解决方案,实在是太弱了。

题意:给您若干山,您可以花费1代价削去1高度,求有k个山峰时的最小代价。

输出k = 1 ~ (n + 1) >> 1的答案。

这最后一个直接限制了我的DP思路。。。后来发现,DP本来就存了这些答案的..毒瘤。

状态表示是f[i][j][0/1],表示前i座山有j个山峰,自己是不是山峰。

比较奇特的是f[i][j][1]要从f[i - 2][j - 1][0/1]转移过来,自然少不了一些奇奇怪怪的特判...

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 typedef long long LL;
 5 const int N = 5005;
 6 
 7 LL f[N][N][2]; // 0 no_hill  1 hill
 8 int a[N], n;
 9 
10 inline int val(int i) {
11     if(i < 1) {
12         return 0;
13     }
14     if(i == 1) {
15         if(a[i] < a[i + 1]) {
16             return 0;
17         }
18         return a[i] - a[i + 1] + 1;
19     }
20     if(a[i - 1] > a[i]) {
21         if(a[i + 1] > a[i]) {
22             return 0;
23         }
24         return a[i] - a[i + 1] + 1;
25     }
26     if(a[i + 1] > a[i - 1] - 1) {
27         return 0;
28     }
29     return a[i - 1] - a[i + 1]; /// error : a[i - 1] - a[i]
30 }
31 inline int vl(int i) {
32     if(i < 1) {
33         return 0;
34     }
35     if(a[i] < a[i + 1]) {
36         return 0;
37     }
38     return a[i] - a[i + 1] + 1;
39 }
40 inline int vx(int i) {
41     if(i > n) {
42         return 0;
43     }
44     if(a[i] < a[i - 1]) {
45         return 0;
46     }
47     return a[i] - a[i - 1] + 1;
48 }
49 
50 int main() {
51     memset(f, 0x3f, sizeof(f));
52     scanf("%d", &n);
53     for(int i = 0; i <= n; i++) {
54         f[i][0][0] = 0;
55     }
56     for(int i = 1; i <= n; i++) {
57         scanf("%d", &a[i]);
58     }
59     int k = (n + 1) >> 1;
60 
61     for(int j = 1; j <= k; j++) {
62         for(int i = 1; i <= n; i++) {
63             if(i == 1) {
64                 if(j == 1) {
65                     f[i][j][1] = vx(2);
66                     //printf("f[1][1][1] = %d\n", f[i][j][1]);
67                 }
68                 continue;
69             }
70             f[i][j][0] = std::min(f[i - 1][j][0], f[i - 1][j][1]);
71             f[i][j][1] = std::min(f[i - 2][j - 1][1] + val(i - 1), f[i - 2][j - 1][0] + vl(i - 1)) + vx(i + 1);
72             //printf("f[%d][%d][0] = %d\n", i, j, f[i][j][0]);
73             //printf("f[%d][%d][1] = %d\n", i, j, f[i][j][1]);
74         }
75     }
76     /*
77     10
78     2 2 4 4 3 1 1 2 3 2
79     */
80     for(int i = 1; i <= k; i++) {
81         printf("%I64d ", std::min(f[n][i][0], f[n][i][1]));
82     }
83 
84     return 0;
85 }
AC代码

 

posted @ 2018-07-31 15:15  garage  阅读(170)  评论(0编辑  收藏  举报