HDU-5115Dire Wolf(区间DP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5115

题目大意:有T组数据,每组数据有n只野狼,接下来一行有n个数据,代表杀掉这只狼要承受的伤害,接下来一行n数据,与上一行相对应,代表杀掉第i只狼后,会受到这只狼左边和右边的附加伤害,问杀掉所有狼的最小伤害是多少?

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

emmmm,区间DP,状态$dp[i][j]$表示的是杀死区间$[i,j]$所耗费的最小代价,那么跟合并石子的有些类似,我们枚举区间长度,枚举起点,得到终点,再枚举分割点,只不过有一点点不太一样。它的状态转移方程是这样的:$dp[l][r]=min(dp[l][r],dp[l][mid-1]+a[mid]+dp[mid+1][r]+b[l-1]+b[r+1])$。emmm,感觉可以望文生义了。。。。

以下是AC代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int mac=250;
const int inf=1e8+10;

int a[mac],b[mac];
int dp[mac][mac];

int main()
{
    int t,n,Case=0;
    scanf ("%d",&t);
    while (t--){
        scanf ("%d",&n);
        memset(b,0,sizeof b);
        for (int i=1; i<=n; i++)
            for (int j=i; j<=n; j++)
                dp[i][j]=inf;
        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++) dp[i][i]=a[i]+b[i-1]+b[i+1];
        for (int len=2; len<=n; len++){
            for (int l=1; l+len-1<=n; l++){
                int r=l+len-1;
                for (int mid=l; mid<=r; mid++)
                    dp[l][r]=min(dp[l][r],dp[l][mid-1]+a[mid]+dp[mid+1][r]+b[l-1]+b[r+1]);
            }
        }
        printf ("Case #%d: %d\n",++Case,dp[1][n]);
    }
    return 0;
}
posted @ 2020-07-07 23:34  lonely_wind  阅读(225)  评论(0编辑  收藏  举报