zoukankan      html  css  js  c++  java
  • POJ 2161 Chandelier(树状DP)

    一、题意

    首先是对题目的翻译。给出一个长长的字符串,这个字符串描述了一个吊灯。对于给字符串只有两种操作数——'a'为一个吊灯灯珠,将改灯珠入栈,一位阿拉伯数字K,代表一个环,将把该数字前面k位数都出栈并且穿成一个环,并将该环重新入栈(作为一个单元)。由此可以得到一颗神奇的树——每个节点的若干子节点呈现循环数组的关系。因而此处有对于同构的定义为:再该环上各个小串的相对位置不变。于是,要求一个新的字符串,能够成上述字符转的一个同构的树,在这个基础上求出最小的“最大栈空间”大小。

    二、思路

    首先设dp[i]为将第i个节点及其子树全部入栈的最小栈大小。对于其第一个入栈的子树,认为此时的最高栈高度为k,则dp[i]=main(dp[i],dp[tar]+i)。此时应当枚举起点并且找到使得值最小的起点。

    (红书说是使用单调栈实现O(N)的求出这个值得具体大小,但是经过隔壁队YC大佬指点发现不是单调栈而是一个简单思路(复杂度O(n))对于每个起点的特定顺序,必然有,最大值为上一个的最大值-1,或者上一个的起点+m-1。于是这样就可以O(1)的找出每一组的最大值,直接对比就好)

    //#include<bits/stdc++.h>
    #include<vector>
    #include<stack>
    #include<iostream>
    #include<string.h>
    #include<stdio.h>
    using namespace std;
    #define veci vector<int>
    #define stai stack<int>
    
    const long long MAXN=1e4+233;
    veci G[MAXN];
    stai ss;
    char str[MAXN];
    int length;
    int dp[MAXN];
    int pos[MAXN];
    
    int deal(int now)
    {
        int len=G[now].size();
        int maxx=dp[G[now][0]];
        for(int i=0;i<len;++i)
        {
            maxx=max(maxx,dp[G[now][i]]+i);
        }
        int ans=maxx;
        for(int i=1;i<len;++i)
        {
            maxx=max(maxx-1,dp[G[now][i-1]]+len-1);
            if(ans>maxx)
            {
                pos[now]=i;
                ans=maxx;
            }
        }
        return ans;
    }
    
    void dfs(int now)
    {
        int len=G[now].size();
        if(len==0)
        {
            dp[now]=1;return ;
        }
        for(int i=0;i<len;++i)
        {
            int tar=G[now][i];
            dfs(tar);
        }
        dp[now]=deal(now);
    }
    
    void show(int now)
    {
        int len=G[now].size();
        if(len==0)
        {
            cout<<"a";return ;
        }
        for(int i=0;i<len;++i)
        {
            int pp=pos[now]+i;
            pp%=len;
            int tar=G[now][pp];
            show(tar);
        }
        cout<<G[now].size();
    }
    
    void init()
    {
    //    gets(str+1);
        length=strlen(str+1);
        memset(dp,0,sizeof(dp));
        memset(pos,0,sizeof(pos));
        int ll=0;
        for(int i=1;i<=length;++i)
        {    
            
            G[i].clear();
                ll=max(ll,(int)ss.size());
            if(str[i]!='a')
            {
                int len=str[i]-'0';
                stai s2;
                for(int j=0;j<len;++j)
                {
    //                int tar=ss.top();
                    s2.push(ss.top());
                    ss.pop();
    //                G[i].push_front(tar);
    //                G[i].push_back(tar);
                }
                while(!s2.empty())
                {
                    G[i].push_back(s2.top());
                    s2.pop();
                }
            
            }    ss.push(i);
        }
        dfs(length);
        cout<<dp[length]<<"
    ";
        show(length);
        cout<<"
    ";
    //    cout<<endl<<ll<<endl;
        
    }
    
    
    int main()
    {
        cin.sync_with_stdio(false);
        while(cin>>(str+1))init();
        
        return 0;
    }
  • 相关阅读:
    【我当项目经理那些年】管理杂谈—三个火枪手
    数据库模糊搜索时,关键字中有%号,怎么办?
    【<私活案例1>】 某游戏网首页PS设计和Html静态效果源码
    递归算法及经典递归例子代码实现
    C++编程命名规范
    【<私活案例2>】 某电力局领导收费凭证小工具
    【<私活案例3>】 获取某市网站普通高中录取分数小工具
    【我当项目经理那些年】建设项目团队—主题晨会
    【自用建设中小型网站工具】快速生成后台
    angualr项目table拖拽列宽效果
  • 原文地址:https://www.cnblogs.com/rikka/p/7809566.html
Copyright © 2011-2022 走看看