Hdu OJ 5115 Dire Wolf (2014ACM/ICPC亚洲区北京站) (动态规划-区间dp)

题目链接: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;
}
View Code
原文地址:https://www.cnblogs.com/aiterator/p/5897159.html