zoukankan      html  css  js  c++  java
  • 【IOI1998】Polygon

    一道区间dp题,不少细节。

    一开始我想定义f[i][j]表示区间[i,j]通过某种合并之后的最大值,之后这道题就等同于“NOI1995石子合并”。

    但是转念一想,这道题有加法和乘法两种运算,如果单看加法,以上思路正确。但是因为乘法的存在,两个较小的数(负数)相乘或许会大于两个最大数相乘,因此以上思路在这里出现了错误。

    因此,我们定义maxx[i][j],minn[i][j]分别表示区间[i,j]通过某种合并之后的最大值、最小值。

    1、如果当前枚举决策为k,而且运算符为加号,则有

     maxx[i][j]=max(maxx[i][k-1]+maxx[k][j]);

     minn[i][j]=min(minn[i][k-1]+minn[k][j]);

     如果运算符为乘号,则有

     maxx[i][j]=max(maxx[i][k-1]*maxx[k][j]);
     maxx[i][j]=max(minn[i][k-1]*minn[k][j]);
     minn[i][j]=min(maxx[i][k-1]*maxx[k][j]);
     minn[i][j]=min(minn[i][k-1]*minn[k][j]);
     minn[i][j]=min(maxx[i][k-1]*minn[k][j]);
     minn[i][j]=min(minn[i][k-1]*maxx[k][j]);

    因此正确的算法就得出来了,我们枚举起始的位置开始计算即可,时间复杂度为O(n4).

    在这里我们将这个环拆开并复制一倍,然后在这个两倍长的链上做一次dp,最后枚举起点选出答案即可,时间复杂度为O(n3).

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 using namespace std;
     5 int n,maxx[60<<1][60<<1],minn[60<<1][60<<1],a[60<<1];
     6 char op[60<<1];
     7 int main() {
     8     cin>>n;
     9     memset(minn,0x3f,sizeof(minn));
    10     memset(maxx,-0x3f,sizeof(maxx));
    11     for(int i=1;i<=n;i++) {
    12         char x;
    13         int y;
    14         cin>>x>>y;
    15         a[i]=a[i+n]=y;
    16         op[i]=op[i+n]=x;
    17     }
    18     for(int i=1;i<=n<<1;i++) 
    19         maxx[i][i]=minn[i][i]=a[i];
    20     for(int i=2;i<=n;i++) {
    21         for(int l=1;l+i-1<=2*n;l++) {
    22             for(int k=l+1;k<=l+i-1;k++) {
    23                 if(op[k]=='t') {
    24                     maxx[l][l+i-1]=max(maxx[l][l+i-1],maxx[l][k-1]+maxx[k][l+i-1]);
    25                     minn[l][l+i-1]=min(minn[l][l+i-1],minn[l][k-1]+minn[k][l+i-1]);
    26                 }
    27                 else {
    28                     maxx[l][l+i-1]=max(maxx[l][l+i-1],maxx[l][k-1]*maxx[k][l+i-1]);
    29                     maxx[l][l+i-1]=max(maxx[l][l+i-1],minn[l][k-1]*minn[k][l+i-1]);
    30                     minn[l][l+i-1]=min(minn[l][l+i-1],maxx[l][k-1]*maxx[k][l+i-1]);
    31                     minn[l][l+i-1]=min(minn[l][l+i-1],minn[l][k-1]*minn[k][l+i-1]);
    32                     minn[l][l+i-1]=min(minn[l][l+i-1],maxx[l][k-1]*minn[k][l+i-1]);
    33                     minn[l][l+i-1]=min(minn[l][l+i-1],minn[l][k-1]*maxx[k][l+i-1]);
    34                 }
    35             }
    36         }
    37     }
    38     int ans=-0x7fffffff;
    39     for(int i=1;i<=n;i++)
    40         ans=max(ans,maxx[i][i+n-1]);
    41     cout<<ans<<endl;
    42     for(int i=1;i<=n;i++)
    43         if(ans==maxx[i][i+n-1]) cout<<i<<" ";
    44     return 0; 
    45 }
    AC Code
  • 相关阅读:
    .NET探索模型路由约定实现伪静态
    .NET中使用DebuggerDisplay轻松定制调试
    .NET探索平台条件编译
    Spring Boot+Logback输出日志到指定路径
    SAPD:FSAF升级版,合理的损失值加权以及金字塔特征选择 | ECCV 2020
    FSAF:嵌入anchor-free分支来指导acnhor-based算法训练 | CVPR2019
    RepPointsV2:更多的监督任务,更强的性能 | NIPS 2020
    RepPoints:微软巧用变形卷积生成点集进行目标检测,创意满满 | ICCV 2019
    CornerNet-Lite:CornerNet粗暴优化,加速6倍还提点了 | BMVC 2020
    SaccadeNet:使用角点特征进行two-stage预测框精调 | CVPR 2020
  • 原文地址:https://www.cnblogs.com/shl-blog/p/10664527.html
Copyright © 2011-2022 走看看