多边形

区间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个点都要赋值
//注意:递推的时候复制的部分也要计算

posted @ 2022-02-09 17:56  __iostream  阅读(183)  评论(0)    收藏  举报