hdu5115(区间dp)
n头狼排成一列,每头狼有两个属性,基础攻击力和附加攻击力,
第i只狼的基础攻击力是ai,附加攻击力是b(i-1) + b(i+1)
消灭一只狼,受到的伤害为基础攻击力+附加攻击力。
问消灭所有的狼受到的最小伤害。
基础攻击力的伤害肯定是要承受的。关键是怎么将附加攻击力的伤害降低到最小
像这种不能从前往后状态转移的dp,应该是用区间dp。
设dp[i][j] 为消灭区间i->j所有狼的最小代价
我们枚举最后一只要消灭的狼k,那么消灭这只狼要收到的附加攻击力是b[i-1] + b[j+1]
所有dp[i][j] = min(dp[i][j],dp[i][k-1] + dp[k+1][j] + b[i-1] + b[j+1]);
最后的答案是dp[1][n] + sum(a[i]);
1 #pragma warning(disable:4996) 2 #pragma comment(linker, "/STACK:1024000000,1024000000") 3 #include <stdio.h> 4 #include <string.h> 5 #include <time.h> 6 #include <math.h> 7 #include <map> 8 #include <set> 9 #include <queue> 10 #include <stack> 11 #include <vector> 12 #include <bitset> 13 #include <algorithm> 14 #include <iostream> 15 #include <string> 16 #include <functional> 17 const int INF = 1 << 30; 18 typedef __int64 LL; 19 /* 20 21 */ 22 const int N = 200 + 10; 23 int b[N]; 24 int dp[N][N]; 25 int solve(int n) 26 { 27 for (int i = 1;i <= n;++i) 28 dp[i][i] = b[i - 1] + b[i + 1]; 29 for (int len = 2;len <= n;++len) 30 { 31 for (int i = 1;i + len-1 <= n;++i) 32 { 33 int j = i + len - 1; 34 dp[i][j] = INF; 35 for (int k = i;k <= j;++k) 36 { 37 //dp[i][j] 表示消灭区间的最小代价,枚举最后一只消灭的狼,那么要受到的附加伤害是b[i-1]+b[j+1] 38 dp[i][j] = std::min(dp[i][j], dp[i][k - 1] + dp[k + 1][j] + b[i - 1] + b[j + 1]); 39 } 40 } 41 } 42 return dp[1][n]; 43 } 44 int main() 45 { 46 int t, n; 47 int a, ans; 48 scanf("%d", &t); 49 for (int k = 1;k <= t;++k) 50 { 51 ans = 0; 52 scanf("%d", &n); 53 for (int i = 1;i <= n;++i) 54 { 55 scanf("%d", &a); 56 ans += a; 57 } 58 for (int i = 1;i <= n;++i) scanf("%d", &b[i]); 59 printf("Case #%d: %d\n", k, ans + solve(n)); 60 } 61 return 0; 62 }