洛谷 P1880 [NOI1995]石子合并 动规

题目链接: 点我跳转
题目大意: 一个环形的数列,每次合并相邻的两个数,两数之和为得分,求合并所有数的最小得分和最大得分。
题目分析: 很经典的题了,我们可以将环形切开,在链上考虑合并情况。
(以下有关区间的讨论全部在左闭右开的情况下讨论)
我们首先来考虑最小得分的情况。对于每一条链上的合并情况,我们可以将链分成两条较短的链进行考虑。也就是 [ s , t ) [s,t) [s,t)可以分成 [ s , m ) [s,m) [s,m) [ m , t ) [m,t) [m,t)其中 s &lt; m &lt; t s&lt;m&lt;t s<m<t,通过枚举 m m m 就可以考虑到所有情况了。我们可以设 d p [ s , t ) dp[s,t) dp[s,t)为将 [ s , t ) [s,t) [s,t)所有石子合并的得分,那么状态转移方程就是
d p [ s , t ) = m i n ( d p [ s , t ) , d p [ s , m ) + d p [ m , t ) + s u m [ s , t ) ) ; dp[s,t) = min(dp[s,t),dp[s,m)+dp[m,t)+sum[s,t)); dp[s,t)=min(dp[s,t),dp[s,m)+dp[m,t)+sum[s,t));这个式子不难理解: [ s , t ) [s,t) [s,t)的得分是 [ s , m ) [s,m) [s,m) [ m , t ) [m,t) [m,t)的得分之和,再加上 [ s , t ) [s,t) [s,t)的石子总数量。
最大得分与最小得分基本一样,只需将 m i n min min 改为 m a x max max 即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>

using namespace std;

int  dp_mi[110][110],dp_ma[110][110],data[110],sum[210];

int main(){
	int n;
	cin>>n;
	for(int i=0;i<n;i++) cin>>data[i];
	
	for(int i=0;i<n;i++)                // 初始化
		for(int j=0;j<n;j++)
			dp_mi[i][j] = 1e9;
	for(int i=0;i<n;i++)dp_mi[i][(i+1)%n] = 0;
	
	for(int i=0;i<=2*n;i++)sum[i+1] = data[i%n];  //这两行的目的是方便计算[s,t)区间和
	for(int i=1;i<=2*n;i++)sum[i] += sum[i-1];    //使得 [s,t)区间和 = sum[t] - sum[s]
	
	for(int l=2;l<=n;l++)                   //l是区间长度
		for(int s=0;s<n;s++)                //区间开始的位置
			for(int i=s+1;i<s+l;i++){       //区间中点的位置
				int m = i%n,t = (s+l)%n;         //为了方便表示
				dp_mi[s][t] = min(dp_mi[s][t],dp_mi[s][m]+dp_mi[m][t]+sum[s+l]-sum[s]);
				dp_ma[s][t] = max(dp_ma[s][t],dp_ma[s][m]+dp_ma[m][t]+sum[s+l]-sum[s]);
			}
	int ans = 0x7fffffff;
	
	for(int i=0;i<n;i++)ans = min(ans,dp_mi[i][i]);
	cout<<ans<<endl;
	for(int i=0;i<n;i++)ans = max(ans,dp_ma[i][i]);
	cout<<ans;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值