【洛谷P4342】[IOI1998]Polygon

Polygon

 

比较裸的环形DP(也可以说是区间DP)

将环拆成链,复制到后面,做区间DP即可

#include<iostream>
#include<cstdio>
using namespace std;
#define MAXN 110
#define INF 0x3f3f3f3f
int n,f[MAXN][MAXN][2],ans=-INF;    //f[l][r][0]表示最小值 f[l][r][1]表示最大值 
char b[MAXN];
inline int read_num(){
    int x=0,f=1; char c=getchar();
    while(c<'0'||c>'9') { if(c=='-') f=-1; c=getchar(); }
    while('0'<=c&&c<='9') { x=(x<<3)+(x<<1)+c-'0'; c=getchar(); }
    return x*f;
}
inline char read_char(){
    char c=getchar();
    while(c!='t'&&c!='x') c=getchar();
    return c;
}
inline int Min(int d,int e,int f){
    if(d<e) e=d;
    if(e<f) f=e;
    return f;
}
inline int Max(int d,int e,int f){
    if(d>e) e=d;
    if(e>f) f=e;
    return f;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        b[i-1]=read_char();
        b[i+n-1]=b[i-1];
        f[i][i][1]=read_num();
        f[i+n][i+n][1]=f[i+n][i+n][0]=f[i][i][0]=f[i][i][1];
    }
    b[0]=0;
    for(int len=2;len<=n;len++)
     for(int l=1;l+len-1<=2*n;l++){
         int r=l+len-1;
         f[l][r][1]=-INF; f[l][r][0]=INF;
         for(int k=l;k<r;k++)
          if(b[k]=='t'){
              f[l][r][0]=min(f[l][r][0],f[l][k][0]+f[k+1][r][0]);
              f[l][r][1]=max(f[l][r][1],f[l][k][1]+f[k+1][r][1]);
          }
         else{
             f[l][r][0]=Min(f[l][r][0],f[l][k][0]*f[k+1][r][1],f[l][k][1]*f[k+1][r][0]);
             f[l][r][1]=Max(f[l][r][1],f[l][k][0]*f[k+1][r][0],f[l][k][1]*f[k+1][r][1]);
         }
     }
    for(int i=1;i<=n;i++)
     ans=max(ans,f[i][i+n-1][1]);
    printf("%d\n",ans);
    for(int i=1;i<=n;i++)
     if(f[i][i+n-1][1]==ans) printf("%d ",i);
    puts("");
    return 0;
}

 

posted @ 2018-06-23 17:09  yjk  阅读(145)  评论(0编辑  收藏  举报