区间dp不用说了吧
主要在于要考虑好几种情况
表示区间的最大值
考虑如果是加
就直接加就是了
但如果是乘
却不一定了
考虑到有可能最大值会由两个最小的负数相乘而来的
所以我们还要维护一个区间最小值
而区间最小值的乘有可能由最小值乘最小值,最大值乘最小值(正*负)而来
所以每次合并区间都要枚举所以可能
#include<algorithm>
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
inline int read(){
char ch=getchar();
int res=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
return res*f;
}
int f[105][105][2],a[105],op[105],n;//0是最小值,1是最大值
char ch;
int main(){
n=read();
for(int i=1;i<=n;i++){
cin>>ch;
if(ch=='t'){
op[i+n-1]=op[i-1]=1;
}
else op[i+n-1]=op[i-1]=2;
a[i]=a[i+n]=read();
}
for(int i=1;i<=2*n;i++){
f[i][i][0]=f[i][i][1]=a[i];
}
for(int len=1;len<n;len++){
for(int l=1;l+len<=2*n;l++){
int r=(l+len);
int g1=-1e4,g2=1e4;
for(int k=l;k<r;k++){
if(op[k]==2){
g1=max(max(f[l][k][1]*f[k+1][r][1],f[l][k][0]*f[k+1][r][0]),g1);
g2=min(min(g2,f[l][k][0]*f[k+1][r][0]),min(f[l][k][1]*f[k+1][r][0],f[l][k][0]*f[k+1][r][1]));
}
else{
g1=max(g1,f[l][k][1]+f[k+1][r][1]);
g2=min(g2,f[l][k][0]+f[k+1][r][0]);
}
}
f[l][r][0]=g2;
f[l][r][1]=g1;
}
}
int maxn=-1e7,k=0;
for(int i=1;i<=n;i++){
if(f[i][i+n-1][1]>maxn){
k=i,maxn=f[i][i+n-1][1];
}
}
cout<<maxn<<'
';
for(int i=1;i<=n;i++){
if(f[i][i+n-1][1]==maxn){
cout<<i<<" ";
}
}
}