N - Slimes.atcoder Dp题单
https://atcoder.jp/contests/dp
题目大意
https://atcoder.jp/contests/dp/tasks/dp_n
给你一组数据,这个数据相邻两个合并,合并的代价是这两个的数值和
求最小代价
这个是超级经典的区间dp,所以写下来
code
void solve(){
int n;cin>>n;
vector<int>a(n+1),pre(n+1);
vector<vector<int>>f(n+1,vector<int>(n+1));
for(int i=1;i<=n;i++){
cin>>a[i];
pre[i]=pre[i-1]+a[i];
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
f[i][j]=1e18;
}
f[i][i]=0;
}
for(int i=n;i>=1;i--){
for(int j=i+1;j<=n;j++){
for(int k=i;k<j;k++)
f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+pre[j]-pre[i-1]);
}
}
cout<<f[1][n]<<endl;
}
分析
对于每个区间(i,j)其最小的合并代价,就是等于两个子区间的合并代价,加上j到i的和(这里用前缀和)
枚举左端点i右端点j以及他们中间的某个位置k,然后取min
之所以i是倒着的是因为在你计算i=1作为左端点的时候,你得先知道他的子区间(比如2作为左端点)的代价,所以要反过来

浙公网安备 33010602011771号