【区间dp】P4342 [IOI1998]Polygon

这道题目第一步划分时,可以直接将其延长一倍,然后就直接进行操作,剩下的就是普通的区间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;
}

猜你喜欢

转载自blog.csdn.net/andyc_03/article/details/107643934