• [IOI1998]Polygon


    luogu传送门

    题解

    一道经典的区间DP,既又环形结构,又需要思考怎样维护“最优子结构”的性质

    首先我们不难想到用dp[l,r]表示第l个节点和第r个节点合并后最大顶点上的最大值

    如果只是有加法运算,其实就与合并石子无异

    但问题来了——有乘法

    所以如果我们只维护最大值,显然不对

    例如:5*5<-9*-9

    这启示我们同时维护一个最小值

    我们简单来说:

    乘法

    最大值 维护: 最大乘最大 最小乘最小

    最小值 维护: 最大乘最大  最小乘最小  前大乘后小  前小乘后大

    加法 

    最大值 维护: 最大加最大 

    最小值 维护: 最小加最小 

    这样下来这个题就不难了qwq

    CODE

    #include<cstdio>
    #include<algorithm>
    #define mxx 0x7fffffff
    using namespace std;
    int n,ans=-mxx,a[150],mx[150][150],mn[150][150];
    char c[150];
    int main()
    {
        register int i,j,k,len;
        scanf("%d
    ",&n);
        for(i=1;i<=n;++i) scanf("%c %d",&c[i],&a[i]),getchar(),a[n+i]=a[i],c[n+i]=c[i];
        for(i=1;i<=(n<<1);++i) for(j=1;j<=(n<<1);++j) mx[i][j]=-mxx,mn[i][j]=mxx;
        for(i=1;i<=(n<<1);++i) mx[i][i]=mn[i][i]=a[i];
        for(len=1;len<=n;++len)
          for(i=1,j=len;j<=(n<<1);++i,++j)
              for(k=i;k<j;++k)
              {
                if(c[k+1]=='x')
                {
                    mx[i][j] = max(mx[i][j],max(mx[i][k]*mx[k+1][j],mn[i][k]*mn[k+1][j])); 
                    mn[i][j] = min(mn[i][j],min(mx[i][k]*mx[k+1][j],min(mn[i][k]*mn[k+1][j],min(mn[i][k]*mx[k+1][j],mx[i][k]*mn[k+1][j])))); 
                }
                else if(c[k+1]=='t')
                {
                    mx[i][j] = max(mx[i][j],mx[i][k]+mx[k+1][j]);
                    mn[i][j] = min(mn[i][j],mn[i][k]+mn[k+1][j]);
                }
            }    
        for(i=1;i<=n;++i) ans=max(ans,mx[i][i+n-1]);    
        printf("%d
    ",ans);
        for(i=1;i<=n;++i) if(ans==mx[i][i+n-1]) printf("%d ",i);
        return 0;
    }
  • 相关阅读:
    偏函数 匿名函数 高阶函数 map filter reduce
    函数
    Python的字符串格式化
    集合
    列表 元组 字典
    字符串
    数字
    Python基础-杂项
    Java 和C/C++的“语法”上的差异!
    MySQL基础原创笔记(一)
  • 原文地址:https://www.cnblogs.com/yearning/p/11397116.html
Copyright © 2020-2023  润新知