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
", k, ans + solve(n));
60     }
61     return 0;
62 }
View Code
原文地址:https://www.cnblogs.com/justPassBy/p/4765476.html