【动态规划笔记】区间dp:合并果子_i++

【动态规划笔记】区间dp:合并果子_ci_02

 

【动态规划笔记】区间dp:合并果子_算法_03

 初始化:一堆果子不需要合并,所以dp[i][i]=0

既然之前说过我们需要枚举k来划分i和j,那么如果通过枚举i和j进行状态转移,很显然某些k值时并不能保证已经确定过所需状态。

 

如,i=1 to 10,j=1 to 10,k=1 to 9.当i=1,j=5,k=3时,显然状态f[k+1][j]没有结果

解决方法:先枚举小区间

for(int len=2;len<=n;i++){
     for(int i=1;i+len-1<=n;i++){          int j=i+len-1;
          for(int k=i;k<j;k++){
             dp[i][j]=dp[i][k]+dp[k+1][j]+sum[i]-sum[j-1];
       }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.


保证区间长度len=j-i+1先从2一直枚举到n

代码:

#include<iostream>
#include<string.h> 
using namespace std;
int dp[10][10];
int sum[10];
int main()
{
	memset(dp,0x3f,100);

	int a[10];
	int n;
	cin>>n;
	sum[0]=0; 
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		sum[i]=sum[i-1]+a[i];
		dp[i][i]=0;
	}
	for(int len=2;len<=n;len++){
		for(int i=1;i+len-1<=n;i++){
			int j=i+len-1;
			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]);
			}
		}
	}
	cout<<dp[1][n];	
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.