HDU 5115 Dire Wolf(区间DP)

Description
n只狼排成一排,每只狼有攻击力ai和攻击加成bi,攻击加成是增强相邻狼的攻击力的,一个冒险者要打败这n只狼,每次打败一只狼需要造成和这只狼的攻击力(包括相邻狼的加成)相同的伤害,但是如果一只狼已经被打败,那么其攻击加成会消失,问这个冒险者打败这n只狼需要造成的最小伤害
Input
第一行为一整数T表示用例组数,每组用例第一行为一整数n表示狼的数量,第二行n个整数ai表示每只狼的攻击力,第三行n个整数表示每只狼的攻击加成
Output
输出这个冒险者打败这n只狼需要造成的最小伤害
Sample Input
2
3
3 5 7
8 2 0
10
1 3 5 7 9 2 4 6 8 10
9 4 1 2 1 2 1 4 5 1
Sample Output
Case #1: 17
Case #2: 74
Solution
区间DP,以dp[i][j]表示冒险者打败[i,j]中所有狼所需造成的最小伤害值,设这个冒险者最后打败的一只狼为k,其中i<=k<=j,那么我们有递推方程
dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k+1][j]+a[k]+b[i-1]+b[j+1])
dp[1][n]即为所求
Code

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 222
#define INF 0x3f3f3f3f
int T,n,a[maxn],b[maxn],dp[maxn][maxn];
int DP(int l,int r)
{
    if(~dp[l][r])return dp[l][r];
    if(l==r)return dp[l][r]=a[l]+b[l-1]+b[l+1];
    if(l>r)return 0;
    dp[l][r]=INF;
    for(int k=l;k<=r;k++)
        dp[l][r]=min(dp[l][r],DP(l,k-1)+DP(k+1,r)+a[k]+b[l-1]+b[r+1]);
    return dp[l][r];
}
int main()
{
    scanf("%d",&T);
    for(int Case=1;Case<=T;Case++)
    {
        scanf("%d",&n);
        memset(dp,-1,sizeof(dp));
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        for(int i=1;i<=n;i++)scanf("%d",&b[i]);
        b[0]=b[n+1]=0;
        int ans=DP(1,n);
        printf("Case #%d: %d\n",Case,ans);
    }
    return 0;
}

你可能感兴趣的:(HDU 5115 Dire Wolf(区间DP))