luoguP1415 拆分数列 [dp]
题目描述
给出一列数字,需要你添加任意多个逗号将其拆成若干个严格递增的数。如果有多组解,则输出使得最后一个数最小的同时,字典序最大的解(即先要满足最后一个数最小;如果有多组解,则使得第一个数尽量大;如果仍有多组解,则使得第二个数尽量大,依次类推……)。
输入输出格式
输入格式:
共一行,为初始的数字。
输出格式:
共一行,为拆分之后的数列。每个数之间用逗号分隔。行尾无逗号。
输入输出样例
[1]
3456
[2]
3546
[3]
3526
[4]
0001
[5]
100000101
[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
《拆分数列》解题报告
By lzn 动态规划常规题。
第一步先求出最后的那个数最小为多少。(为了叙述方便,记T(i,j)表示从原数列下标i取到j的数字组成的数。)只需正向dp一次,dp1[i]表示前i个数字分成任意多个递增数且最后的数最小时,最后的数为T(dp1[i],i)。则dp1[i]=max(j),(T(dp1[j-1],j-1)<T(j,i))。
第二步要求最后一个数确定的情况下,前面的数字按字典序尽量大的解。类似上面的方法反向动归一次即可。
算法复杂度o(l^3)。由于数据大部分为随机,实际运行效率接近l^2。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
using namespace std; const int maxn=; string str;
int a[maxn],n,dP[maxn],Dp[maxn]; bool cmp(int l1,int r1,int l2,int r2){
while(l1<=r1&&a[l1]==) l1++;
while(l2<=r2&&a[l2]==) l2++;
int le1=r1-l1+,le2=r2-l2+;
if(le1==||le2==) return ;
if(le1!=le2) return le1<le2;
for(int i=;i<le1;i++)
if(a[l1+i]!=a[l2+i]) return a[l1+i]<a[l2+i];
return ;
} //dP[i]=max(j),(T(dP[j-1],j-1)<T(j,i))
void DP1(){
for(int i=;i<=n;i++){
dP[i]=;
for(int j=i;j;j--)
if(cmp(dP[j-],j-,j,i)){
dP[i]=j;
break;
}
// printf("dP[%d] = %d\n",i,dP[i]);
}
} //Dp[i]=max(j) (T(i,j)<T(j+1,f[j+1]))
void DP2(){
Dp[dP[n]]=n;
for(int i=dP[n];a[i-]==;i--) Dp[i-]=n; for(int i=dP[n]-;i;i--){
for(int j=dP[n]-;j>=i;j--)
if(cmp(i,j,j+,Dp[j+])){
Dp[i]=j;
break;
}
// printf("Dp[%d] = %d\n",i,Dp[i]);
}
} void print(int l,int r){
for(int i=l;i<=r;i++)
putchar(a[i]+'');
} void print(){
print(,Dp[]);
int pos=Dp[]+;
while(pos<=n){
putchar(',');
print(pos,Dp[pos]);
pos=Dp[pos]+;
}
} int main(){
cin>>str; n=str.length();
for(int i=;i<n;i++) a[i+]=str[i]-'';
DP1(); DP2();
print();
return ;
}
luoguP1415 拆分数列 [dp]的更多相关文章
- [luoguP1415] 拆分数列(DP)
传送门 t(i,j)表示下标从i到j的数 d[i]表示以i结尾的最小的数的下标 d[i]=max(j) (1<=j<=i && t(d[j-1],j-1)<t(j,i ...
- P1415 拆分数列 DP
传送门: 题意: 将一个数字串分成许多不同的小串,使得这些小串代表的数字严格递增,要求最后一个数字尽可能地小. 然后满足字典序尽可能大. 思路: 由于最后一个数字要尽可能地小,所以先处理出每个数的L[ ...
- 洛谷P1415 拆分数列[序列DP 状态 打印]
题目背景 [为了响应党中央勤节俭.反铺张的精神,题目背景描述故事部分略去^-^] 题目描述 给出一列数字,需要你添加任意多个逗号将其拆成若干个严格递增的数.如果有多组解,则输出使得最后一个数最小的同时 ...
- 洛谷 P1415 拆分数列 解题报告
拆分数列 题目背景 [为了响应党中央勤节俭.反铺张的精神,题目背景描述故事部分略去^-^] 题目描述 给出一列数字,需要你添加任意多个逗号将其拆成若干个严格递增的数. 如果有多组解,则输出使得最后一个 ...
- 洛谷P1415 拆分数列(dp)
题目链接:传送门 题目: 题目背景 [为了响应党中央勤节俭.反铺张的精神,题目背景描述故事部分略去^-^] 题目描述 给出一列数字,需要你添加任意多个逗号将其拆成若干个严格递增的数.如果有多组解,则输 ...
- 洛谷P1415 拆分数列
题目背景 [为了响应党中央勤节俭.反铺张的精神,题目背景描述故事部分略去^-^] 题目描述 给出一列数字,需要你添加任意多个逗号将其拆成若干个严格递增的数.如果有多组解,则输出使得最后一个数最小的同时 ...
- BZOJ 2431: [HAOI2009]逆序对数列( dp )
dp(i,j)表示1~i的全部排列中逆序对数为j的个数. 从1~i-1的全部排列中加入i, 那么可以产生的逆序对数为0~i-1, 所以 dp(i,j) = Σ dp(i-1,k) (j-i+1 ≤ k ...
- BZOJ2431:[HAOI2009]逆序对数列(DP,差分)
Description 对于一个数列{ai},如果有i<j且ai>aj,那么我们称ai与aj为一对逆序对数.若对于任意一个由1~n自然数组成的 数列,可以很容易求出有多少个逆序对数.那么逆 ...
- P1415 拆分数列
传送门 DP数列长度过大无法枚举,考虑DP设f1[i]储存以第i个字符为结尾时,的最后一个数最小时,这个数的开头的位置(很难想有木有)OK,状态有了,方程想一想就出来了:设$num[i][j]$为数列 ...
随机推荐
- KMP 算法学习
KMP算法是用来做字符串匹配的.关于字符串匹配,最简单最容易想到的方法是暴利查找,使用双重for循环处理. 该方法的时间复杂度为O((n-m+1)*m) (n为目标串T长度,m为模式串P长度, 从T中 ...
- Makefile中的$(addprefix),添加前缀,指定目标生成目录
先给大家看段Makefile的代码吧: INCLUDE_DIR=usr/java/jdk1..0_25/include \ usr/java/jdk1..0_25/include/linux INCL ...
- linux php5.6 安装
如果之前有安装其他版本PHP,请先卸载干净 配置yum源 追加CentOS 6.5的epel及remi源. # rpm -Uvh http://ftp.iij.ad.jp/pub/linux/fe ...
- Python3-unittest测试框架之Mock接口联调
unittest测试框架之Mock接口联调 unittest.mock 是一个用于测试的Python库.它允许使用mock对象替换受测试系统的部分,并对它们如何已经被使用进行断言. Mock使用前提 ...
- rest_framework框架实现之(认证)
一认证 我们可以想想,我们要访问一个页面,需不需要对其进行认证,希望进入页面的时候看到哪些内容,一般是根据用户的不同而不同 首先,我们先设计一个表,如何知道对方通过了验证,我们可以考虑给其加一个tok ...
- JavaIO流之File操作
IO流: File: File(文件/文件夹地址)构造函数: public File(String path); public File(String parentPath, String child ...
- 【leetcode】966. Vowel Spellchecker
题目如下: Given a wordlist, we want to implement a spellchecker that converts a query word into a correc ...
- Centos剔除在线用户
CentOS踢除已登录用户的方法: 1.>先按下w查看用户终端号 2.>执行pkill -kill -t pts/1 (pts/1为w指令看到的用户终端号)命令
- python3 schedule定时任务
import time import schedule # cd C:\Python36-32\Scripts pip install schedule # py文件名字不能叫schedule,否则会 ...
- PHP FILTER_VALIDATE_REGEXP 过滤器
定义和用法 FILTER_VALIDATE_REGEXP 过滤器根据兼容 Perl 的正则表达式来验证值. Name: "validate_regexp" ID-number: 2 ...