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;
}

浙公网安备 33010602011771号