洛谷p1775石子合并(弱化版)
Posted 江上舟摇
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷p1775石子合并(弱化版)相关的知识,希望对你有一定的参考价值。
题目链接:https://www.luogu.com.cn/problem/P1775;
思路:(单列石子合并)
经典的区间dp,我们要考虑的是如何获得最小的代价,就可以用dp[i][j]来表示从第i堆石子到第j堆石子所付出的最小代价,sum[i]是从开始到i的石堆和
例如:
当两堆两堆合并的时候,我们可给出样例是3,2,4,5。那这样来说,最小代价就是(2+4)+(2+4+5),
那么可以这么理解:dp[1][2]=dp[1][1]+dp[2][2]+sum[2]-sum[0];
sum[2]-sum[0]是前缀和求法,可以理解为从区间0到区间2之间的数字和。
那么三堆合并也是如此,
我们给出如上样例,2可以与4合并,也可以与5合并
那么dp[1][3]=min(dp[1][1]+dp[2][3],dp[1][2]+dp[3][3])+sum[3]-sum[0];
推广 到第k堆,i=<k<=j,
dp[i][j]=min(dp[i][k]+dp[k+1][j])+sum[i][j]。
这里是不是有些不理解?我会在代码中把注释标注完善
参考代码:
#include<bits/stdc++.h> using namespace std; int n; int sum[310];//记录从开始到i的石子堆之和 int dp[310][310];//表示从i到j合并所付出的最小代价 int a[310]; int minval() for(int len=1;len<n;len++)//区间长度,即i到j的长度 for(int i=1;i<=n-len;i++)//起点i,好好体会为什么是n-len,因为n-len就是终点 int j=i+len;i//终点j dp[i][j]=INT_MAX;//标兵作用,求最小值要先把他的标兵定于为最大值 for(int k=i;k<j;k++) dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]);//它本身和从i到k所付出的代价加上从k到j的代价以及二者之间的石堆 return dp[1][n];//1--n所付出的最少代价 int main() ios::sync_with_stdio(false); cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; sum[i]=sum[i-1]+a[i];//从i到j区间的和 dp[i][i]=0;//初始化表示从i到i不需要代价 cout<<minval()<<endl; return 0;
戒骄戒躁,任重道远
以上是关于洛谷p1775石子合并(弱化版)的主要内容,如果未能解决你的问题,请参考以下文章