Luogu P4342 [IOI1998]Polygon
https://www.luogu.com.cn/problem/P4342
题面
每个顶点用整数标记,每个边用符号+(加)或符号*(乘积)标记。
每次可以删掉一条边,将两个点运算完和起来,问最大得分
\(n\leq 50\)
分析
显然区间DP,加法就是加法
由于数可能是负数,乘法需要将最小最大值乘起来
所以维护最小最大值即可
#include<bits/stdc++.h>
#define ll long long
const int INF=1e9;
using namespace std;
const int N=1005;
int n,a[N],f[N][N],g[N][N];
bool b[N];
char op[10];
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++) {
scanf("%s%d",op,&a[i]);
a[i+n]=a[i],b[i+n]=b[i]=(op[0]=='t')?0:1;
}
for(int i=1;i<=n+n;i++) {
for(int j=1;j<=n+n;j++) f[i][j]=INF,g[i][j]=-INF;
}
for(int i=1;i<=n+n;i++) f[i][i]=g[i][i]=a[i];
for(int l=2;l<=n;l++) {
for(int i=1;i<=n+n-l+1;i++) {
int j=i+l-1;
for(int k=i+1;k<=j;k++) {
if(b[k]==0) f[i][j]=min(f[i][k-1]+f[k][j],f[i][j]),g[i][j]=max(g[i][k-1]+g[k][j],g[i][j]);
else {
f[i][j]=min((ll)f[i][j],min((ll)f[i][k-1]*g[k][j],min((ll)g[i][k-1]*f[k][j],min((ll)f[i][k-1]*f[k][j],(ll)g[i][k-1]*g[k][j]))));
g[i][j]=max((ll)g[i][j],max((ll)f[i][k-1]*g[k][j],max((ll)g[i][k-1]*f[k][j],max((ll)f[i][k-1]*f[k][j],(ll)g[i][k-1]*g[k][j]))));
}
}
}
}
int Ans=0;
for(int i=1;i<=n;i++) {
Ans=max(Ans,g[i][i+n-1]);
}
printf("%d\n",Ans);
for(int i=1;i<=n;i++) {
if(g[i][i+n-1]==Ans) printf("%d ",i);
}
return 0;
}

浙公网安备 33010602011771号