zoukankan      html  css  js  c++  java
  • Polygon

    Polygon

    给出一个n个点n条边的环,每条边会有一个运算符号,但只能是(+, imes),而点上会有一个数字,现在的操作第一步,选择一条边丢掉,接下来的所有操作,每次可以选择条边,删去,并把这删去的边所连的两个点合并称一个顶点,数字为删去边的两个点的数字进行删去的边上的符号,现在询问剩下的最后一个点上的数字的最大值,(nleq 50)

    实际上注意到数据范围很下,于是我们先拆一条边,就是一条链了,接着合并两个相邻的顶点,于是发现这应该是一个区间合并问题,而环我们可以利用拆环成链中的再补一截的方法优化。

    注:点的编号起点随你定,因为这是一个环

    又注意到加法是恒满足最优子结构性质,但是乘法不满足,原因在于最小值也能组成最优解,所以要分类讨论。

    因此设(f[0/1][l][r])分别表示合并点l到r的剩下的一个点最小值和最大值,于是不难有

    [if(+),f[0][l][r]=min_{k=l}^{r-1}(f[0][l][k]+f[0][k+1][r]) ]

    [if( imes),f[0][l][r]=min_{k=l}^{r-1}min_{p=q=0}^1(f[p][l][k] imes f[q][k+1][r]) ]

    [if(+),f[1][l][r]=max_{k=l}^{r-1}(f[1][l][k]+f[1][k+1][r]) ]

    [if( imes),f[1][l][r]=max_{k=l}^{r-1}max_{p=q=0}^1(f[p][l][k] imes f[q][k+1][r]) ]

    边界:(f[0][i][i]=f[1][i][i]=)第i个点上的数字,(i=1,2,...,n),f[0][][]无限大,f[1][][]无限小

    答案:(max_{i=1}^nf[1][i][i+n-1])

    参考代码:

    阶段实现

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define il inline
    #define ri register
    #define ll long long
    #define llmax 1e16
    using namespace std;
    char c[101];
    ll dp[2][101][101];
    int stack[101],st;
    il void get(char&);
    template<class free>il free Max(free,free);
    template<class free>il free Min(free,free);
    int main(){
        int n,n2;scanf("%d",&n),n2=n<<1;
        memset(dp[0],66,sizeof(dp[0]));
        memset(dp[1],-66,sizeof(dp[1]));
        for(int i(1);i<=n;++i)
            get(c[i]),scanf("%lld",&dp[0][i][i]),
                c[i+n]=c[i],dp[1][i][i]=dp[1][i+n][i+n]
                =dp[0][i+n][i+n]=dp[0][i][i];
        for(int i,j(1),k,p,q;j<=n2;++j)
            for(i=j-1;i;--i)
                for(k=i;k<j;++k)
                    if(c[k+1]=='t')
                        dp[0][i][j]=Min(dp[0][i][j],dp[0][i][k]+dp[0][k+1][j]),
                            dp[1][i][j]=Max(dp[1][i][j],dp[1][i][k]+dp[1][k+1][j]);
                    else for(p=0;p<2;++p)
                             for(q=0;q<2;++q)
                                 dp[0][i][j]=Min(dp[0][i][j],dp[p][i][k]*dp[q][k+1][j]),
                                     dp[1][i][j]=Max(dp[1][i][j],dp[p][i][k]*dp[q][k+1][j]);
        ll ans(-llmax);
        for(ri int i(1);i<=n;++i)
            if(dp[1][i][i+n-1]>ans)
                ans=dp[1][i][i+n-1],stack[st=1]=i;
            else if(dp[1][i][i+n-1]==ans)
                stack[++st]=i;
        printf("%lld
    ",ans);
        for(int i(1);i<=st;++i)
            printf("%d ",stack[i]);
        return 0;
    }
    template<class free>
    il free Max(free a,free b){
        return a>b?a:b;
    }
    template<class free>
    il free Min(free a,free b){
        return a<b?a:b;
    }
    il void get(char&c){
        while(c=getchar(),c==' '||c=='
    '||c=='
    ');
    }
    

    dfs实现

    #include <iostream>
    #include <cstdio>
    #define il inline
    #define ri register
    #define ll long long
    #define llmax 1e16
    #define lsy akioi tql
    using namespace std;
    char c[101];
    int stack[101],st;
    ll dp[2][101][101];
    bool deal[2][101][101];
    il void get(char&);
    il ll dfs(int,int,int);
    template<class free>il free comp(int,free,free);
    int main(){
        int n,i;scanf("%d",&n);
        for(i=1;i<=n;++i)
            get(c[i]),c[i+n]=c[i],
                scanf("%lld",&dp[0][i][i]),
                dp[1][i][i]=dp[0][i+n][i+n]
                =dp[1][i+n][i+n]=dp[0][i][i],
                deal[0][i][i]=deal[1][i][i]=
                deal[0][i+n][i+n]=deal[1][i+n][i+n]=true;
        ll ans(-llmax);
        for(int i(1);i<=n;++i)
            if(ans<dfs(1,i,i+n-1))
                ans=dfs(1,i,i+n-1),stack[st=1]=i;
            else if(ans==dfs(1,i,i+n-1))stack[++st]=i;
        printf("%lld
    ",ans);for(int i(1);i<=st;++i)printf("%d ",stack[i]);
        return 0;
    }
    template<class free>
    il free comp(int p,free a,free b){
        return (p^(a<b))?a:b;
    }
    il ll dfs(int p,int l,int r){
        if(deal[p][l][r])return dp[p][l][r];
        dp[p][l][r]=p?-llmax:llmax,deal[p][l][r]|=true;
        for(int k(l),a,b;k<r;++k)
            if(c[k+1]=='t')
                dp[p][l][r]=comp(p,dp[p][l][r],dfs(p,l,k)+dfs(p,k+1,r));
            else for(a=0;a<2;++a)
                     for(b=0;b<2;++b)
                         dp[p][l][r]=comp(p,dp[p][l][r],dfs(a,l,k)*dfs(b,k+1,r));
        return dp[p][l][r];
    }
    il void get(char &c){
        while(c=getchar(),c==' '||c=='
    '||c=='
    ');
    }
    
  • 相关阅读:
    DEM地形渲染中光源的方向
    python GDAL安装运行后提示找不到proj.db
    AO——将函数栅格数据集保存到磁盘
    arcgis影像分幅图裁剪
    arcgis判断线是否穿过面
    WSL 使用vscode写python
    python-gdal支持filegdb读写
    Chapter5 生长因子、受体和癌症
    Chapter6 胞内信号网络
    【转】B树、B+树、B*树
  • 原文地址:https://www.cnblogs.com/a1b3c7d9/p/10924095.html
Copyright © 2011-2022 走看看