石子归并 51Nod - 1021

Posted Jozky86

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了石子归并 51Nod - 1021相关的知识,希望对你有一定的参考价值。

石子归并 51Nod - 1021

题意:

现要将石子有次序地合并成一堆。规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的代价。计算将N堆石子合并成一堆的最小代价

题解:

区间dp的入门题
dp[i][j]表示从第i堆合并到第j堆需要多少代价
sum[i]为前i堆的数量和
如果我们现在要把第i堆合并到第j堆,有一个k,(i<k<j),(dp[i][k]+dp[k+1][j])取最小,然后+sum[j]-sum[i-1]合并这一堆的费用
dp[ i ][ j ] = min(dp[ i ][ k ] + dp[ k + 1 ][ j ],dp[ i ][ j ])+sum[ j ] - sum [ i - 1 ]

代码:

#include<bits/stdc++.h>
#define debug(a,b) printf("%s = %d\\n",a,b);
typedef long long ll;
using namespace std;

inline int read(){
   int s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);
   return s*w;
}
const int maxn=1e3+9;
int a[maxn];
int sum[maxn];
int dp[maxn][maxn];
const int INF=1e9;
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		sum[i]=sum[i-1]+a[i]; 
	}
	for(int len=2;len<=n;len++){//枚举的区间长度 
		for(int i=1;i+len-1<=n;i++){//左端点  
			dp[i][i+len-1]=INF;
			for(int k=i;k<=i+len-1;k++){
				dp[i][i+len-1]=min(dp[i][i+len-1],dp[i][k]+dp[k+1][i+len-1]+(sum[i+len-1]-sum[i-1]));
			}
		} 
	}
	cout << dp[1][n] << endl; ;
    return 0; 
}

以上是关于石子归并 51Nod - 1021的主要内容,如果未能解决你的问题,请参考以下文章

51Nod 1021 石子归并

51nod 1021 石头归并

石子归并 51Nod - 1021

51nod 1021 石子归并(dp)

石子归并 51Nod - 1021

51nod 1021 石子归并