[笔记]石子合并问题整理(冬眠中)

[Contents]

  • 无环,朴素算法,\(O(n^3)\)
  • 有环,朴素算法,\(O(n^3)\)
  • GrsiaWachs、四边形不等式优化

无环,朴素算法,\(O(n^3)\)

例题:P1775 石子合并(弱化版)

\(f[i][j]\)表示\(i\sim j\)的最小得分,枚举长度\(len=2\sim n\),对于每个长度,枚举左端点\(l\),算出右端点\(r\),然后再枚举从分割位置\(k=l\sim r-1\),注意需要前缀和维护一下区间和。

\(f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]+a[r]-a[l-1])\)

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,a[310],dp[310][310];
int main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i],a[i]+=a[i-1];
	for(int len=2;len<=n;len++){
		for(int l=1;l+len-1<=n;l++){
			int r=l+len-1;
			dp[l][r]=INT_MAX;
			for(int k=l;k<r;k++){
				dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r]+a[r]-a[l-1]);
			}
		}
	}
	cout<<dp[1][n];
	return 0;
}

有环,朴素算法,\(O(n^3)\)

例题:P1880 [NOI1995] 石子合并

\(a\)重复一次接到末尾,长度就是\(2n\),此时可以转化为无环的做法。\(len\)还是\(2\sim n\),但是\((l,r)\)区间最多可以延伸到\(2n\)。最终求出\(max(f[1][n],f[2][n+1],f[3][n+2],…,f[n-1][2n])\)即可,\(min\)同理。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,a[210];
int dp[210][210],dp2[210][210];
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		a[n+i]=a[i];
	}
	for(int i=1;i<=2*n;i++) a[i]+=a[i-1];
	for(int len=2;len<=n;len++){
		for(int l=1;l+len-1<=2*n;l++){
			int r=l+len-1;
			dp[l][r]=INT_MIN;
			dp2[l][r]=INT_MAX;
			for(int k=l;k<r;k++){
				dp[l][r]=max(dp[l][r],dp[l][k]+dp[k+1][r]+a[r]-a[l-1]);
				dp2[l][r]=min(dp2[l][r],dp2[l][k]+dp2[k+1][r]+a[r]-a[l-1]);
			}
		}
	}
	int maxx=INT_MIN,minn=INT_MAX;
	for(int i=1;i<=n;i++){
		maxx=max(maxx,dp[i][i+n-1]);
		minn=min(minn,dp2[i][i+n-1]);
	}
	cout<<minn<<endl<<maxx;
	return 0;
}

后两种信息量有点大,可能会鸽一段时间

posted @ 2024-04-03 22:12  Sinktank  阅读(39)  评论(0编辑  收藏  举报
★CLICK FOR MORE INFO★ TOP-BOTTOM-THEME
Enable/Disable Transition
Copyright © 2023 ~ 2024 Sinktank - 1328312655@qq.com
Illustration from 稲葉曇『リレイアウター/Relayouter/中继输出者』,by ぬくぬくにぎりめし.