オオカミはn人並んでおり、各オオカミには攻撃力とボーナス値の2つの属性があります。オオカミの実際の攻撃力は、自身の攻撃力に隣接するオオカミのボーナス値を加えたものに等しくなります。殺された後、オオカミは隣接します。オオカミの攻撃力へのボーナスがキャンセルされると同時に、殺されたオオカミに隣接していた2匹のオオカミが隣接するオオカミになります。すべてのオオカミを殺すための最小ダメージ値は何ですか?
入力の
複数のグループを入力します。最初の行に1つ、
各グループに1つ、n(n <= 200)、および
各オオカミの攻撃力を表すn個の数字(0 <= a [i] <= 1e5)
。各オオカミのボーナス値を表します(0 <= b [i] <= 5e4)
出力
サンプルの各セットはケースを出力し、次に回答を出力します。
サンプルインプット
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
サンプル出力
ケース#1:17
ケース#2:74
ヒント
最初のサンプルでは、マットはダイアウルフを左から右に倒します。彼は5+ 5 + 7 = 17ポイントのダメージを受けます。これは、彼が受けなければならない最小のダメージです。
区間DPテンプレートの質問では、最初にdp [i] [j]の後半、つまり部分j> iを最大値に初期化することを忘れないでください。これは、後半が前のステージの動的遷移方程式を更新するために使用されるためです。.b配列の左側と右側に現在の攻撃値と隣接するボーナスを追加します
dp[j][k]=min(dp[j][k],dp[j][x-1]+a[x]+dp[x+1][k]+b[j-1]+b[k+1]);
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <map>
#include <stack>
#include <set>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdio>
#define ls (p<<1)
#define rs (p<<1|1)
#define ll long long
using namespace std;
const int maxn = 500;
const int INF = 0x3f3f3f3f;
ll dp[maxn][maxn];
ll a[maxn],b[maxn];
void solve(){
int t;
cin>>t;
int cas=0;
while(t--){
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
cin>>b[i];
b[0]=0;
b[n+1]=0;
memset(dp,0,sizeof(dp));
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++){
for(int j=1;j<=n-i+1;j++){
int k=i+j-1;
for(int x=j;x<=k;x++){
dp[j][k]=min(dp[j][k],dp[j][x-1]+a[x]+dp[x+1][k]+b[j-1]+b[k+1]);
}
}
}
printf("Case #%d: %d\n",++cas,dp[1][n]);
}
}
int main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
solve();
return 0;
}