zoukankan      html  css  js  c++  java
  • 洛谷P1415 拆分数列

    题目背景

    【为了响应党中央勤节俭、反铺张的精神,题目背景描述故事部分略去^-^】

    题目描述

    给出一列数字,需要你添加任意多个逗号将其拆成若干个严格递增的数。如果有多组解,则输出使得最后一个数最小的同时,字典序最大的解(即先要满足最后一个数最小;如果有多组解,则使得第一个数尽量大;如果仍有多组解,则使得第二个数尽量大,依次类推……)。

    输入输出格式

    输入格式:

    共一行,为初始的数字。

    输出格式:

    共一行,为拆分之后的数列。每个数之间用逗号分隔。行尾无逗号。

    输入输出样例

    输入样例#1:
    [1]
    3456
    [2]
    3546
    [3]
    3526
    [4]
    0001
    [5]
    100000101
    
    输出样例#1:
    [1]
    3,4,5,6
    [2]
    35,46
    [3]
    3,5,26
    [4]
    0001
    [5]
    100,000101
    

    说明

    【题目来源】

    lzn改编

    【数据范围】

    对于10%的数据,输入长度<=5

    对于30%的数据,输入长度<=15

    对于50%的数据,输入长度<=50

    对于100%的数据,输入长度<=500

    解析:

    进行两次dp第一次dp dp1[i] 表示以第i个数字为结尾的 1~i串的最小结尾串的开始长度

    第二次dp dp2[i]表示 以第[i]个数字为开头的开始串的最大长度

    然后很显然啊 先第一次找出后面最小的,然后去掉找出的最后的 dp第二次找出前面最大的依次输出即可

    当然dp的时候要保持递增性,这个有很多细节,包括去0全0等

    (思路及代码均来自candy博客)=.=代码还比他的丑

    代码:

    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    int n;
    string s("#"),op;
    int dp1[1011];
    int dp2[1011];
    int note[1001]; 
    
    
    bool can(int l1,int r1,int l2,int r2)
    // 其实这两个就是L1 ~R1的一个数字,L2 ~ R2的一个数字
    //判断是否是严格递增
    {
        while(l1 <= r1 && note[l1] == 0)
        {
            if(l1 == r1)return false;
            l1++;
        }
        while(l2 <= r2 && note[l2] == 0)
        {
            if(l2 == r2)return false;
            l2++;
        }
        /**/
        int len1 = r1 - l1 + 1;
        int len2 = r2 - l2 + 1;
        if(len1 < len2)return true;
        if(len1 > len2)return false;
        
        for(int i = 0;i < len1;i++)
        {
            if(note[l1 + i] == note[l2 + i])continue;
            return note[l1 + i] < note[l2 + i];
        }
        return false;//都相同的情况下 
    } 
    
    
    
    void dp()
    {
        for(int i = 1;i <= n;i++)
        {
            dp1[i] = 1; // 向前扩展最多一位(因为他没法不扩展,扩展就可能变大) 
            for(int j = i;j >= 1;j--)
                if(can(dp1[j - 1],j - 1,j,i)) // 
                {
                        dp1[i] = j;break; 
                }
        }
        
        dp2[dp1[n]] = n;int zz = dp1[n];
        while(note[zz - 1] == 0)dp2[zz - 1] = n,zz--;
        
        for(int i = dp1[n] - 1;i >= 1;i--)
        {
            for(int j = dp1[n] - 1;j >= i;j--)
                if(can(i,j,j+1,dp2[j + 1]))
                {
                    dp2[i] = j;break;
                }
        }
        
        
    }
    
    int main()
    {
        cin >> op;
        s += op;
        n = s.size() - 1;
        for(int i = 1;i <= n;i++)
            note[i] = s[i] - '0';
        dp();
        int now = 1;
        while(now <= n)
        {
            if(now != 1)printf(",");
            for(int i = now;i <= dp2[now];i++)printf("%d",note[i]);
            now = dp2[now] + 1;
    
        }    
        return 0;
    }
  • 相关阅读:
    C开发注意事项
    Teamcenter ITK
    Teamcenter SOA开发源码: 打印对象信息
    Teamcenter服务端开发环境配置
    Teamcenter中UID和对象之间相互转化
    Teamcenter 打开数据集
    Teamcenter中SOA调用user service
    63.display:none与visibility:hidden的区别?
    60.为什么要初始化CSS样式
    58.用纯CSS创建一个三角形的原理是什么?
  • 原文地址:https://www.cnblogs.com/luoyibujue/p/7657955.html
Copyright © 2011-2022 走看看