设f(l,r,0)表示区间[l,r]操作后的最大值,f(l,r,1)表示区间[l,r]操作后的最小值,简单的区间合并即可。
可以把第一条边断掉,然后把这后面的N个点复制一遍,直接做N*2长度的区间dp。
答案是max:f(i,i+N-1,0)。
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
int N;
int f[105][105][2];
int val[105];
char op[105];
int main(){
// freopen("in.txt","r",stdin);
cin>>N;
cin>>op[N]>>val[1];
for(int i=2;i<N;i++)
cin>>op[i-1]>>val[i];
cin>>op[N-1]>>val[N];
for(int i=N+1;i<=N*2;i++)
op[i]=op[i-N],val[i]=val[i-N];
for(int i=1;i<=N*2;i++)
f[i][i][0]=f[i][i][1]=val[i];
for(int len=2;len<=N;len++)
for(int i=1;i+len-1<=N*2;i++){
int j=i+len-1,MAX=-INF,MIN=INF;
for(int k=i;k+1<=j;k++){
if(op[k]=='t'){
MAX=max(MAX,f[i][k][0]+f[k+1][j][0]);
MIN=min(MIN,f[i][k][1]+f[k+1][j][1]);
}
else{
MAX=max(MAX,f[i][k][0]*f[k+1][j][0]);
MIN=min(MIN,f[i][k][0]*f[k+1][j][1]);
MIN=min(MIN,f[i][k][1]*f[k+1][j][0]);
MAX=max(MAX,f[i][k][1]*f[k+1][j][1]);
MIN=min(MIN,f[i][k][1]*f[k+1][j][1]);
}
}
f[i][j][0]=MAX;f[i][j][1]=MIN;
}
int ans=0,tot=0,out[55];
for(int i=1;i<=N;i++){
if(f[i][i+N-1][0]>ans){
out[tot=1]=i;
ans=f[i][i+N-1][0];
}
else if(f[i][i+N-1][0]==ans)
out[++tot]=i;
}
printf("%d\n",ans);
for(int i=1;i<=tot;i++)
printf("%d ",out[i]);
return 0;
}