因為某些申必原因被刪除
題目描述
給出一列數字,需要你新增任意多個逗號將其拆成若干個嚴格遞增的數。如果有多組解,則輸出使得最後乙個數最小的同時,字典序最大的解(即先要滿足最後乙個數最小;如果有多組解,則使得第乙個數盡量大;如果仍有多組解,則使得第二個數盡量大,依次類推……)。
輸入輸出格式
輸入格式:
共一行,為初始的數字。
輸出格式:
共一行,為拆分之後的數列。每個數之間用逗號分隔。行尾無逗號。
輸入輸出樣例
input
[1]output3456
[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
【資料範圍】
對於10%的資料,輸入長度<=5
對於30%的資料,輸入長度<=15
對於50%的資料,輸入長度<=50
對於100%的資料,輸入長度<=500
研究表明這道題用乙個dp似乎是寫不出來的。
所以我們為不把這道題分成幾個小的dp??
因為題目說首先保證最後的數盡量小,所以要先把最後乙個數的最小值dp出來。設f[i]表示把第i個數之前的數分開,最後乙個數的開始的下標。
很容易(難)想到狀態轉移方程:
f[i]=max(j)∣a(i,j)>a(f[j−1],j−1),1≤j≤i
**:
for
(int i=
1;i<=n;i++
)}
pd那個函式是判斷j~i組成的數是否比f[j-1],j-1之間的數大。
之所以j要從後往前列舉,是為了保證讓它遞增的盡量慢一些,這樣才能保證最後乙個數盡量小。
搞♂完以後,就是讓第乙個數以及後面的數盡量大啦!
為了讓第乙個數盡量大,那麼就從後往前dp。
設f2[i]表示把i~n之間的數分開,最前面的數的結尾下標。
狀態轉移方程:
f[i]=max(j) | a(i,j)注意一下邊界,f2[f[n]]=n
還有注意處理它前面的0(不然會gg)
code:
f2[f[n]
]=n;
for(
int i=f[n]-1
;i&&a[i]==0
;i--
) f2[i]
=n,cnt++
;for
(int i=f[n]-1
-cnt;i>=
1;i--)}
}
這裡的j也是從後往前列舉的。
是為了讓它遞減的慢一點,這樣可以保證前面的數盡量大。
完整**:
#include
using
namespace std;
#define maxn 505
char a1[maxn]
;int a[maxn]
,cnt;
int f[maxn]
,n,f2[maxn]
;intpd(
int l1,
int r1,
int l2,
int r2)
inline
void
print
(int l,
int r)
intmain()
} f2[f[n]
]=n;
for(
int i=f[n]-1
;i&&a[i]==0
;i--
) f2[i]
=n,cnt++
;for
(int i=f[n]-1
-cnt;i>=
1;i--)}
}int pos=
1,flag=1;
while
(pos<=n)
return0;
}
注意那個pd函式,之所以不開bool是因為排除兩個數相等的尷尬情況
因為題目要求是嚴格遞增的。所以第二個dp如果直接用的話 a<=b 的情況的就會直接轉移了,從而得出錯誤的答案
不信試試這個
input
output2,22,222就是這個樣子啦!
洛谷 P1415 拆分數列 解題報告
為了響應 勤節儉 反鋪張的精神,題目背景描述故事部分略去 給出一列數字,需要你新增任意多個逗號將其拆成若干個嚴格遞增的數。如果有多組解,則輸出使得最後乙個數最小的同時,字典序最大的解 即先要滿足最後乙個數最小 如果有多組解,則使得第乙個數盡量大 如果仍有多組解,則使得第二個數盡量大,依次類推 共一行...
P1415 拆分數列(記憶化搜尋)
這麼麻煩的題敲出來沒wa真的是舒服 原題 題意 給出一列數字,需要你新增任意多個逗號將其拆成若干個嚴格遞增的數。如果有多組解,則輸出使得最後乙個數最小的同時,字典序最大的解 即先要滿足最後乙個數最小 如果有多組解,則使得第乙個數盡量大 如果仍有多組解,則使得第二個數盡量大,依次類推 解析 大小比較函...
luoguP1415 拆分數列 dp
給出一列數字,需要你新增任意多個逗號將其拆成若干個嚴格遞增的數。如果有多組解,則輸出使得最後乙個數最小的同時,字典序最大的解 即先要滿足最後乙個數最小 如果有多組解,則使得第乙個數盡量大 如果仍有多組解,則使得第二個數盡量大,依次類推 輸入格式 共一行,為初始的數字。輸出格式 共一行,為拆分之後的數...