• IOI 98 (POJ 1179)Polygon(区间DP)


    很容易想到枚举第一步切掉的边,然后再计算能够产生的最大值。

    联想到区间DP,令dp[i][l][r]为第一步切掉第i条边后从第i个顶点起区间[l,r]能够生成的最大值是多少。

    但是状态不好转移,因为操作的符号不仅有‘+’,还有‘*’,加法的话,父区间的最大值显然可以从子区间的最大值相加得出。

    乘法的话,父区间的最大值除了由子区间的最大值相乘得出,还可以由子区间的最小值相乘得出。

    所以,多定义一维状态。 dp[i][l][r][flag]表示第一步切掉第i条边后从第i个顶点起区间[l,r]能够生成的最大值/最小值是多少?

    转移的话很简单

    dp[i][l][r][0]=min(dp[i][l][k][0]+dp[i][k+1][r][0])(操作符为+),min(dp[i][l][k][0]*dp[i][k+1][r][1], dp[i][l][k][1]*dp[i][k+1][r][0])(操作符为*).

    dp[i][l][r][1]=max(dp[i][l][k][1]+dp[i][k+1][r][1])(操作符为+),min(dp[i][l][k][0]*dp[i][k+1][r][0], dp[i][l][k][1]*dp[i][k+1][r][1])(操作符为*).

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define eps 1e-8
    # define MOD 1000000007
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    int Scan() {
        int res=0, flag=0;
        char ch;
        if((ch=getchar())=='-') flag=1;
        else if(ch>='0'&&ch<='9') res=ch-'0';
        while((ch=getchar())>='0'&&ch<='9')  res=res*10+(ch-'0');
        return flag?-res:res;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=55;
    //Code begin...
    
    int ans[N], num[N], dp[N][N][N][2], n;
    char s[N][2];
    bool vis[N][N][N][2];
    
    int dfs(int x, int l, int r, int flag)
    {
        if (vis[x][l][r][flag]) return dp[x][l][r][flag];
        vis[x][l][r][flag]=1;
        if (l==r) return dp[x][l][r][flag]=num[(x+l-2)%n+1];
        if (flag) {
            int ans=-INF;
            FO(i,l,r) {
                if (s[(x+i-1)%n+1][0]=='t') ans=max(ans,dfs(x,l,i,1)+dfs(x,i+1,r,1));
                else ans=max(ans,max(dfs(x,l,i,1)*dfs(x,i+1,r,1),dfs(x,l,i,0)*dfs(x,i+1,r,0)));
            }
            return dp[x][l][r][flag]=ans;
        }
        else {
            int ans=INF;
            FO(i,l,r) {
                if (s[(x+i-1)%n+1][0]=='t') ans=min(ans,dfs(x,l,i,0)+dfs(x,i+1,r,0));
                else ans=min(ans,min(dfs(x,l,i,0)*dfs(x,i+1,r,1),dfs(x,l,i,1)*dfs(x,i+1,r,0)));
            }
            return dp[x][l][r][flag]=ans;
        }
    }
    int main ()
    {
        int ma=-INF, flag=1;
        scanf("%d",&n);
        FOR(i,1,n) scanf("%s%d",s[i],num+i);
        FOR(i,1,n) ma=max(ma,dfs(i,1,n,1));
        printf("%d
    ",ma);
        FOR(i,1,n) if (dp[i][1][n][1]==ma) printf(flag?"%d":" %d",i), flag=0;
        putchar('
    ');
        return 0;
    }
    View Code
  • 相关阅读:
    lombok的介绍及使用
    java后端导入excel将数据写入数据库
    java后端导出excel表格
    eclipse maven打war包
    java后端树形菜单使用递归方法
    mybatis一对多查询
    @transactional作用和事务
    zookeeper安装
    Solr单机版安装
    jstat 简介(2)
  • 原文地址:https://www.cnblogs.com/lishiyao/p/6527072.html
Copyright © 2020-2023  润新知