這是一道DP題...我竟然有那麼半個小時思考非DP解決方案,實在是太弱了。ide
題意:給您若干山,您能夠花費1代價削去1高度,求有k個山峯時的最小代價。spa
輸出k = 1 ~ (n + 1) >> 1的答案。code
這最後一個直接限制了個人DP思路。。。後來發現,DP原本就存了這些答案的..毒瘤。blog
狀態表示是f[i][j][0/1],表示前i座山有j個山峯,本身是否是山峯。string
比較奇特的是f[i][j][1]要從f[i - 2][j - 1][0/1]轉移過來,天然少不了一些奇奇怪怪的特判...it
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 }