zoukankan      html  css  js  c++  java
  • 《算法竞赛进阶指南》0x53区间DP POJ1179Ploygon

    题目链接:http://poj.org/problem?id=1179

    问题:给定一个环,其中边上是操作,有加和乘两种,点上是数值,执行的操作如下:找一条边断开,然后任选边开始将边相连的两个点进行运算后变成新的点,计算到最后变成一个点时这个点的最大值。由于合并两个区间的时候,如果操作数是加法的话容易得到和区间的最大值和最小值,如果是乘法的话仅仅知道区间的最大值是不行的,因为可能有两个很小的负数相乘得到的值才是最大值,所以考虑将区间的最小值和最大值信息都进行保存,那么和区间的最小值和最大值一定在两个区间的这两个属性的两两组合的乘积中的最小的一个活着最大的一个。

    唯一的注意点是边的给出是在点之前的,所以k与k+1编号的数进行的运算是使用的第k+1个操作数。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int maxn = 110,inf=10000000;
    int w[maxn];
    char c[maxn];
    int f[maxn][maxn],g[maxn][maxn];
    int n;
    int main(){
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>c[i]>>w[i];
            c[n+i]=c[i];
            w[n+i]=w[i];
        }
        memset(f,-0x3f,sizeof(f));
        memset(g,0x3f,sizeof(g));
        for(int len=1;len<=n;len++)
            for(int i=1;i+len-1<=2*n;i++)
            {
                int j=i+len-1;
                if(len==1)
                    f[i][j]=g[i][j]=w[i];
                else{
                    for(int k=i;k<j;k++){
                        int maxl=f[i][k],minl=g[i][k];
                        int maxr=f[k+1][j],minr=g[k+1][j];
                        char op=c[k+1];
                        if(op=='t'){
                            f[i][j]=max(f[i][j],maxl+maxr);
                            g[i][j]=min(g[i][j],minl+minr);
                        }else{
                            int x1=minl*minr,x2=minl*maxr;
                            int x3=maxl*maxr,x4=maxl*minr;
                            f[i][j]=max(f[i][j],max(max(x1,x2),max(x3,x4)));
                            g[i][j]=min(g[i][j],min(min(x1,x2),min(x3,x4)));
                        }
                    }
                }
             } 
        
        int ans=-inf;
        for(int i=1;i<=n;i++)
            ans=max(ans,f[i][i+n-1]);
        cout<<ans<<endl;
        for(int i=1;i<=n;i++)
            if(f[i][i+n-1]==ans)cout<<i<<" ";
        
        return 0;
    }
  • 相关阅读:
    广播和多播
    nohup和&后台运行,进程查看及终止
    Java知识汇总——思维导图
    linux 基础命令使用
    scp命令详解
    linux 安装crontab执行定时任务
    linux磁盘挂载
    虚拟机安装网络设置
    Android直播实现srs流媒体服务器部署
    java的(PO,VO,TO,BO,DAO,POJO)解释
  • 原文地址:https://www.cnblogs.com/randy-lo/p/13403995.html
Copyright © 2011-2022 走看看