洛谷【动态规划3/4】区间与环形动态规划/树或图上的动态规划

目录

  • P1880 石子合并

P1880 石子合并

#include
using namespace std;
const int maxn = 210;

int n;
int a[maxn]; //每堆石子的个数 
int dp[maxn][maxn];
int sum[maxn];//前缀和数组 
int main(){
	scanf("%d",&n);
	fill(dp[0],dp[0]+maxn*maxn,0x3ffffff);//先计算最小得分 
	for(int i =1;i<=n;i++){
		scanf("%d",&a[i]);
		a[i+n] = a[i];
		dp[i][i] = 0;
		dp[i+n][i+n] = 0;
	}
	sum[0] = 0;
	for(int i=1;i<=n*2;i++){
		sum[i] = sum[i-1]+a[i];
	}
	//计算最小得分
	for(int len=2;len<=n;len++){//区间长度(合并石子堆数)
		for(int i =1;i+len-1<=2*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]);
			}  
		}
	} 
	int ans = 0x3ffffff;
	for(int i=1;i<=n;i++){
		ans = min(ans,dp[i][i+n-1]);
	} 
	cout<<ans<<endl;
	//最大得分
	memset(dp,0,sizeof(dp));
	for(int len=2;len<=n;len++){
		for(int i=1;i+len-1<=2*n;i++){
			int j = i+len-1;
			for(int k =i;k<j;k++){
				dp[i][j] = max(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]);
			}
		}
	}
	ans = 0;
	for(int i=1;i<=n;i++){
		ans = max(ans,dp[i][i+n-1]);
	}
	cout<<ans<<endl;
	return 0;
}

你可能感兴趣的:(刷题)