洛谷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石子合并(弱化版)的主要内容,如果未能解决你的问题,请参考以下文章

洛谷1880 石子合并

洛谷 P1880 石子合并

洛谷 P1880 石子合并

codevs 1048/洛谷 1880:石子归并

区间dp学习笔记

洛谷—— P1775 古代人的难题_NOI导刊2010提高(02)