HDU 5115 Dire Wolf(区间DP)

一道非常经典的区间DP。  一开始没有想明白状态到底该如何表示,因为杀掉一只狼会影响其他狼的攻击力,所以看起来貌似非常难以解决。 

但是如果看出了是区间DP之后,就可以展开DP的常规推理了。   首先,是状态的表示,如何表示状态,这是最重要的一步。   表示出状态以后,还要看他是怎么转移的,以及转移过去的子问题是不是和原问题具有相同的结构和意义。    我们套用区间DP常规的状态表示:d[i][j] 表示杀死第i~j头狼所受到的最小伤害。 那么对于每一层,枚举区间分割点k,将原区间分解成子区间,然后表示先打k两边的狼再杀k。   那么对于区间i~j,由于表示杀死了区间所有的狼,那么肯定会受到第i-1和j+1头狼的伤害加成。

可是这样表示真的是对的吗?  其实通过不断的分解子问题,而每个子问题确实又都是最优结构且无后效性。

细节参见代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 205;
const int INF = 1000000000;
int T,n,kase=0,a[maxn],b[maxn],d[maxn][maxn];
int dp(int i, int j) {
    if(i > j) return 0;
    int& ans = d[i][j];
    if(ans != -1) return ans;
    ans = INF;
    for(int k=i;k<=j;k++)
        ans = min(ans,dp(i,k-1)+a[k]+dp(k+1,j));
    if(ans != INF)
    ans += (b[i-1] + b[j+1]);
    return ans;
}
int main() {
    scanf("%d",&T);
    while(T--) {
        scanf("%d",&n);
        memset(d,-1,sizeof(d));
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=1;i<=n;i++) scanf("%d",&b[i]);
        a[n+1] = b[n+1] = 0;
        int ans = dp(1,n);
        printf("Case #%d: %d\n",++kase,ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值