E28【模板】区间DP 石子合并——信息学竞赛算法_哔哩哔哩_bilibili
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int N=210;
int n,a[N];
ll dp[N][N],sum[N];
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
sum[i]=sum[i-1]+a[i];
}
for(int i=1;i<=n;i++) //计算前缀和
memset(dp,0x3f,sizeof(dp));
for(int i=1;i<=n;i++) dp[i][i]=0;
//已经是一堆的石头不需要再进行合并,代价为0
//区间DP模板
for(int len=2;len<=n;len++)
for(int l=1;(l+len-1)<=n;l++)//区间长度
{
int r=l+len-1;//右端点
for(int k=1;k<r;k++)//插入点
{
dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r]+sum[r]-sum[l-1]);//对不同的分割点进行比较
//dp[l][r]表示对同一区间的不同分割情况进行比较
}
}
cout<<dp[1][n]<<endl;
return 0;
}
选择的顺序不同合并的总代价也不相同


#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int N=210;
int n,a[N];
ll dp[N][N],sum[N];
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];//输入每一堆的数量
for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i];//计算前缀和
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) dp[i][j]=1e18;//全部初始化为最大值
for(int i=1;i<=n;i++) dp[i][i]=0;
//已经是一堆的石头不需要再进行合并,代价为0
//区间DP模板
for(int len=2;len<=n;len++)
for(int l=1;(l+len-1)<=n;l++)//区间长度
{
int r=l+len-1;//右端点
for(int k=1;k<r;k++)//插入点
{
dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r]+sum[r]-sum[l-1]);//对不同的分割点进行比较
//dp[l][r]表示对同一区间的不同分割情况进行比较
}
}
cout<<dp[1][n]<<endl;
return 0;
}

3320

被折叠的 条评论
为什么被折叠?



