题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5115
题目大意:前面有n头狼并列排成一排, 每一头狼都有两个属性--基础攻击力和buff加成, 每一头狼的攻击力等于他自身的基础攻击力加上旁边狼对他的buff加成。 现在你被这群狼围着了, 必须将这些狼全部击败, 你才能逃出, 你每攻击一头狼,收到的伤害是狼的总攻击力。现在问,你逃出这些狼的围攻需要的最小代价(收到的伤害);
解题思路:声明dp数组, dp[i][j]代表从i到j的区间杀死所有狼的最小代价, 然后枚举[i,j]区间中最后杀死的那头狼k。
那么状态方程就很容易写了: dp[i][j] = min(dp[i][j], dp[i][k-1] + dp[k+1][j] + a[k] + b[i-1] + b[j+1])
k为最后一个杀死的, 那么狼k的总攻击力应该为他的基础攻击力a[i],加上他周围两个狼(i-1)和(j+1)的buff加成。
代码如下:
#include<stdio.h> #include<string.h> #include<cmath> #include<queue> #include<algorithm> using namespace std; typedef long long ll; const int INF = 100000007; const int N = 303; int dp[N][N]; int a[N], b[N]; void solve(int cases) { int n; scanf("%d", &n); memset(a, 0, sizeof(a)); memset(b, 0, sizeof(b)); memset(dp, 0, sizeof(dp)); for(int i=1; i<=n; ++ i) scanf("%d", &a[i]); for(int i=1; i<=n; ++ i) scanf("%d", &b[i]); for(int i=1; i<=n; ++ i) for(int j=1; j<=n; ++ j) dp[i][j] = (i<=j?INF:0); for(int i=0; i<n; ++ i) { for(int j=1; j+i<=n; ++ j) { int l = j, r = j+i; for(int k=j; k<=j+i; ++ k) { dp[l][r] = min(dp[l][r], dp[l][k-1] + dp[k+1][r] + a[k] + b[l-1] + b[r+1]); } } } printf("Case #%d: %d ", cases, dp[1][n]); } int main() { int t; scanf("%d", &t); for(int i = 1; i <= t; ++ i) { solve(i); } return 0; }