[IOI1998]Polygon

很早就看到这题了...但因为有个IOI标志,拖到现在才做

由于是以前在书上看到的,就没有想过其他算法,直接区间DP了...

方程式也挺好想的

跟我们平时做数学题求几个数乘积最大差不多

最大的*最大的

最小的*最小的(可能是负数)

这样两种情况

由于求最大中要用到最小值,我们在维护最大同时维护最小

最小的*最小的

最小的*最大的

也是两种情况

再考虑加法

最大:最大+最大

最小:最小+最小

各有一种情况

Tip 上面所述的类似于最大*最大都是左区间最大/小 和右区间最大/小

表达起来大概是这样的

    for(int len=2;len<=n;++len){
        for(int i=1;i+len-1<=2*n;++i){
            int j=i+len-1;
            for(int k=i;k<j;++k){
                if(opt[k+1]=='x')
                    cmax(dpd[i][j],dpd[i][k]*dpd[k+1][j],dpx[i][k]*dpx[k+1][j]),
                    cmin(dpx[i][j],dpd[i][k]*dpx[k+1][j],dpx[i][k]*dpd[k+1][j],dpx[i][k]*dpx[k+1][j]);
                else
                    cmin(dpx[i][j],dpx[i][k]+dpx[k+1][j]),
                    cmax(dpd[i][j],dpd[i][k]+dpd[k+1][j]);
            }
        }
    }

最后的代码

#include<cstdio>
#include<iostream>
#include<cstring>
#define inf (0x7fffffff)
#define writeln(x)  write(x),puts("")
#define writep(x)   write(x),putchar(' ')
using namespace std;
inline int read(){
    int ans=0,f=1;char chr=getchar();
    while(!isdigit(chr)){if(chr=='-') f=-1;chr=getchar();}
    while(isdigit(chr)){ans=(ans<<3)+(ans<<1)+chr-48;chr=getchar();}
    return ans*f;
}void write(int x){
    if(x<0) putchar('-'),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+'0');
}int n,a[155],dpx[155][155],dpd[155][155],ans=-inf;char opt[55];
inline void cmin(int &a,int b){if(b<a) a=b;}
inline void cmin(int &a,int b,int c){cmin(a,b),cmin(a,c);}
inline void cmin(int &a,int b,int c,int d){cmin(a,b,c),cmin(a,d);}
inline void cmax(int &a,int b){if(a<b)a=b;}
inline void cmax(int &a,int b,int c){cmax(a,b),cmax(a,c);}
 
int main(){
    n=read();
    for(register int i=1;i<=n;++i) cin>>opt[i]>>a[i];
    for(register int i=1;i<=n;++i) opt[i+n]=opt[i],a[i+n]=a[i];
    for(int i=1;i<=n*2;++i)
        for(int j=1;j<=n*2;++j)
            (i==j)?(dpx[i][i]=dpd[i][i]=a[i]):(dpd[i][j]=-inf,dpx[i][j]=inf);
    for(int len=2;len<=n;++len){
        for(int i=1;i+len-1<=2*n;++i){
            int j=i+len-1;
            for(int k=i;k<j;++k){
                if(opt[k+1]=='x')
                    cmax(dpd[i][j],dpd[i][k]*dpd[k+1][j],dpx[i][k]*dpx[k+1][j]),
                    cmin(dpx[i][j],dpd[i][k]*dpx[k+1][j],dpx[i][k]*dpd[k+1][j],dpx[i][k]*dpx[k+1][j]);
                else
                    cmin(dpx[i][j],dpx[i][k]+dpx[k+1][j]),
                    cmax(dpd[i][j],dpd[i][k]+dpd[k+1][j]);
            }
        }
    }
    for(int i=1;i<=n;++i) cmax(ans,dpd[i][i+n-1]);writeln(ans);
    for(int i=1;i<=n;i++) if(dpd[i][i+n-1]==ans) writep(i);
    return 0;
}
全部评论

相关推荐

秋招进行到现在终于能写总结了。完全没想到战线会拉这么长,过程会如此狼狈,不过更应该怪自己太菜了。好在所有的运气都用在了最后,也是有个去处。背景:双2本硕科班,无竞赛,本科一段研究所实习,硕士一段大厂暑期实习但无转正。技术栈是C++&nbsp;&amp;&nbsp;Golang,实习是客户端音视频(而且是鸿蒙端开发),简历两个C++项目一个Golang项目。主要投递岗位:后端,cpp软开,游戏服务端,测开,以及一些不拘泥于Java的岗位。从8月起总共投递123家公司,笔试数不清了,约面大约30家。offer/oc/意向:友塔游戏(第一个offer,面试体验很好,就是给钱好少南瑞继保(计算机科班点击就送(限男生),不...
乡土丁真真:佬很厉害,羡慕~虽然我还没有到校招的时候,也想讲一下自己的看法:我觉得不是CPP的问题,佬的背书双2,技术栈加了GO,有两段实习。投了123,面了30.拿到11个offer。这个数据已经很耀眼了。这不也是CPP带来的吗?当然也不止是CPP。至少来说在这个方向努力过的也会有好的结果和选择。同等学历和项目选java就会有更好的吗?我个人持疑问态度。当然CPP在方向选择上确实让人头大,但是我觉得能上岸,至于最后做什么方向,在我看来并不重要。至于CPP特殊,有岗位方向的随机性,java不是不挑方向,只是没得选而已。也希望自己以后校招的时候能offer满满
点赞 评论 收藏
分享
头像
11-09 12:17
清华大学 C++
out11Man:小丑罢了,不用理会
点赞 评论 收藏
分享
11-18 09:44
Java
小白也想要offer:简历别放洋屁,搞不还还放错了,当然你投外企除外,以上纯属个人观点
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务