上次北京赛现场赛的题了,昨天做了道区间dp,突然想起来这道题,都是很类似的,就翻出来做了做
刚开始像昨天做的那道一样,老想着怎么逆推,后来发现这道题应该正着推
其实正推和逆推乍看起来是很相似的,只不过一个是dp[i][j]表示i、j左右还有其他狼时消灭掉i-j这段消耗的费用,一个是表示最后只剩i-j时消灭掉这段的费用
总结一下昨天那道区间dp和今天的区间dp的相同点,发现区间dp适用于费用会随着时间的推移,或者说dp的进行不断变化
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
const int inf=999999999;
int a[205],b[205];
int dp[205][205],n;
void init(){
for(int i=0;i<205;i++){
for(int j=0;j<205;j++){
dp[i][j]=inf;
}
}
b[n+1]=0;
for(int i=1;i<=n;i++) dp[i][i]=a[i]+b[i-1]+b[i+1];
for(int i=1;i<n;i++) dp[i][i+1]=min(dp[i][i]+a[i+1]+b[i+2]+b[i-1],dp[i+1][i+1]+a[i]+b[i-1]+b[i+2]);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int T;
scanf("%d",&T);
int cas=1;
while(T--) {
scanf("%d",&n);
for(int i=1;i<=n;i++) {
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++) {
scanf("%d",&b[i]);
}
init();
for(int l=3;l<=n;l++){
for(int i=1;i+l-1<=n;i++){
int j=i+l-1;
dp[i][j]=min(dp[i][j],dp[i+1][j]+a[i]+b[i-1]+b[j+1]);
dp[i][j]=min(dp[i][j],dp[i][j-1]+a[j]+b[j+1]+b[i-1]);
for(int k=i+1;k<=j-1;k++){
dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k+1][j]+b[i-1]+b[j+1]+a[k]);
}
//printf("dp[%d][%d] :%d\n",i,j,dp[i][j]);
}
}
printf("Case #%d: %d\n",cas++,dp[1][n]);
}
}原文:http://blog.csdn.net/lj94093/article/details/45567183