这道题目第一步划分时,可以直接将其延长一倍,然后就直接进行操作,剩下的就是普通的区间dp了
由于dp的内容有乘积,有可能是两个负数的最小值乘来,所以需要维护一个最小值
代码
#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
int n,ans=-inf;
int a[105];
int f[150][150],g[150][150];
char c[105];
int main(){
freopen("a.in","r",stdin);
scanf("%d\n",&n);
for(int i=1;i<=n;i++)
scanf("%c %d",&c[i],&a[i]),getchar(),a[n+i]=a[i],c[n+i]=c[i];
for(int i=1;i<=(n<<1);i++)
for(int j=1;j<=(n<<1);j++)
f[i][j]=-inf,g[i][j]=inf;
for(int i=1;i<=(n<<1);i++)
f[i][i]=g[i][i]=a[i];
for(int len=2;len<=n;len++)
for(int i=1,j=len;j<=(n<<1);i++,j++)
for(int k=i;k<j;k++)
{
if(c[k+1]=='x')
{
f[i][j]=max(f[i][j],max(f[i][k]*f[k+1][j],max(g[i][k]*g[k+1][j],max(f[i][k]*g[k+1][j],g[i][k]*f[k+1][j]))));
g[i][j]=min(g[i][j],min(f[i][k]*f[k+1][j],min(g[i][k]*g[k+1][j],min(f[i][k]*g[k+1][j],g[i][k]*f[k+1][j]))));
}
else if(c[k+1]=='t')
{
f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]);
g[i][j]=min(g[i][j],g[i][k]+g[k+1][j]);
}
}
for(int i=1;i<=n;i++)
ans=max(ans,f[i][i+n-1]);
printf("%d\n",ans);
for(int i=1;i<=n;i++)
if(f[i][i+n-1]==ans)
printf("%d ",i);
return 0;
}