P4342 [IOI 1998] Polygon

与 P1063能量项链 类似,都是环且只能选取相邻的两个节点合并,考虑 区间 DP

处理环:断环成链

\(f[i][j]\) 表示合并区间 \([i,j]\) 得到的最高分数

加法:\(f[i][j]=max(f[i][j],f[i][k]+f[k+1][j])\)

乘法: \(f[i][j]=max(f[i][j],f[i][k]*f[k+1][j])\)

但是,顶点数字都在 \([−32768,32767]\) 的范围内,考虑负数情况,负负得正,最大值可能由两个负数相乘得到,维护最大值与最小值

第二问,删一条变,变成链状,判断 \(f[i][i+n-1]\) 是否等于 ans 即可

#include<bits/stdc++.h>
using namespace std;
const long long inf=-1e18;
int n,w[105],op[105];
long long mn[105][105],mx[105][105],ans=inf;
char c;
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>c>>w[i];
		if(c=='t') op[i]=1;
		else op[i]=2;
		w[i+n]=w[i];
		op[i+n]=op[i];
	}
	memset(mx,0x80,sizeof(mx));
	memset(mn,0x3f,sizeof(mn));
	for(int i=1;i<=2*n;i++){
		mx[i][i]=w[i];
		mn[i][i]=w[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++){
				if(op[k+1]==1){
					mx[i][j]=max(mx[i][j],mx[i][k]+mx[k+1][j]);
					mn[i][j]=min(mn[i][j],mn[i][k]+mn[k+1][j]);
				}
				else{
					mx[i][j]=max(mx[i][j],mx[i][k]*mx[k+1][j]);
					mx[i][j]=max(mx[i][j],mn[i][k]*mn[k+1][j]);
					mn[i][j]=min(mn[i][j],mn[i][k]*mn[k+1][j]);
					mn[i][j]=min(mn[i][j],mn[i][k]*mx[k+1][j]);
					mn[i][j]=min(mn[i][j],mx[i][k]*mn[k+1][j]);
				}
			}
		}
	}
	for(int i=1;i<=n;i++) ans=max(ans,mx[i][i+n-1]);
	cout<<ans<<'\n';
	for(int i=1;i<=n;i++){
		if(mx[i][i+n-1]==ans) cout<<i<<" ";
	}
	cout<<'\n';
	return 0;
}
posted @ 2026-06-11 17:01  Aguanenti  阅读(5)  评论(0)    收藏  举报