1. 程式人生 > >洛谷P1415 拆分數列

洛谷P1415 拆分數列

表示 spa 情況下 一個數 精神 continue algorithm code 說明

題目背景

【為了響應黨中央勤節儉、反鋪張的精神,題目背景描述故事部分略去^-^】

題目描述

給出一列數字,需要你添加任意多個逗號將其拆成若幹個嚴格遞增的數。如果有多組解,則輸出使得最後一個數最小的同時,字典序最大的解(即先要滿足最後一個數最小;如果有多組解,則使得第一個數盡量大;如果仍有多組解,則使得第二個數盡量大,依次類推……)。

輸入輸出格式

輸入格式:

共一行,為初始的數字。

輸出格式:

共一行,為拆分之後的數列。每個數之間用逗號分隔。行尾無逗號。

輸入輸出樣例

輸入樣例#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; }

洛谷P1415 拆分數列