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 }