多边形
区间dp: 将l~r的区间进行合并 通过枚举分界点来转移状态
环形问题: 断环城链 复制后接起来 之后重点在于只枚举长度为n的区间即可
#include <iostream>
#include <cstdio>
#include <cstring>
const int N=105;
const int INF=0x3f3f3f3f;
using namespace std;
int read()
{
int x=0,f=0,c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return f?-x:x;
}
int a[N],n;
bool op[N];
int f[N][N][2];
int main()
{
n=read();
for(int i=1;i<=n;i++)
op[i]=(getchar()=='t'?1:0),a[i]=read();
for(int i=1;i<=n;i++) a[i+n]=a[i],op[i+n]=op[i];
for(int i=1;i<=n*2;i++)
for(int j=1;j<=n*2;j++)
f[i][j][0]=-INF,f[i][j][1]=INF;
for(int i=1;i<=n*2;i++) f[i][i][0]=f[i][i][1]=a[i];
for(int len=2;len<=n;len++)
for(int l=1;l+len-1<=n*2;l++)
{
int r=l+len-1;
for(int k=l;k<r;k++)
{
if(op[k+1])
{
f[l][r][0]=max(f[l][r][0],f[l][k][0]+f[k+1][r][0]);
f[l][r][1]=min(f[l][r][1],f[l][k][1]+f[k+1][r][1]);
}
else
{
f[l][r][0]=max(f[l][r][0],f[l][k][0]*f[k+1][r][0]);
f[l][r][0]=max(f[l][r][0],f[l][k][1]*f[k+1][r][1]);
f[l][r][1]=min(f[l][r][1],f[l][k][1]*f[k+1][r][1]);
f[l][r][1]=min(f[l][r][1],f[l][k][0]*f[k+1][r][1]);
f[l][r][1]=min(f[l][r][1],f[l][k][1]*f[k+1][r][0]);
}
}
}
int ans=-INF;
for(int i=1;i<=n;i++)
ans=max(ans,f[i][i+n-1][0]);
printf("%d\n",ans);
for(int i=1;i<=n;i++)
if(ans==f[i][i+n-1][0]) printf("%d ",i);
return 0;
}
}
//注意:是2*n个点都要赋值
//注意:递推的时候复制的部分也要计算

浙公网安备 33010602011771号