這麼麻煩的題敲出來沒wa真的是舒服~原題:
題意:
給出一列數字,需要你新增任意多個逗號將其拆成若干個嚴格遞增的數。如果有多組解,則輸出使得最後乙個數最小的同時,字典序最大的解(即先要滿足最後乙個數最小;如果有多組解,則使得第乙個數盡量大;如果仍有多組解,則使得第二個數盡量大,依次類推……)。
解析:
大小比較函式:
int
compare
(int ll,
int rr,
int l,
int r)
return0;
}
第一要求最後乙個數最小,那麼先從後往前,得到乙個最小的滿足要求的段。這個段只要可以做到滿足要求,那麼答案段就是這個。(這個串的前面可能有字首0)
這個過程需要用到記憶化搜尋,即l~r這個區間可能被搜尋多次,如果這個區間不能達到要求,那麼標記-剪枝。
找到最後一段後,再要求前面的數大。那麼列舉從大開始,1~l-1
到1~1
,如果滿足要求則打標記,ans[i]=1表示第i個字母後面插逗號。
往後搜的過程也需要記憶化搜尋-打標記,我第一發忘記vis[l][r]=1;
就tle了。
細節:
乙個段全是0也判不符合,要求打標記。
最後一段l==1則直接輸出即可。
最後一段l前面可能有字首0,所以往後搜的結束標誌為:右邊界落在為0的那個區間內。
#include
using namespace std;
char x[
509]
;int len;
intcompare
(int ll,
int rr,
int l,
int r)
return0;
}bool isempty
(int l,
int r)
bool vis[
509]
[509];
//記憶化
bool check
(int l,
int r)
if(l==1)
return true;
for(
int i=l-
1;i>=
1;i--
)else
break
;//數變大就更不行了
} vis[l]
[r]=1;
//標記
return0;
}int l,ll;
bool ans[
509]
;bool check2
(int l,
int r)if(
compare
(l,r,l,len)
>=0)
//搜尋結束
if(r>=ll-
1&&r<=l-1)
for(
int i=l-
1;i>r;i--)if
(compare
(r+1
,i,l,r)
<=0)
continue;if
(check2
(r+1
,i))
} vis[l]
[r]=1;
//標記
return0;
}int
main()
}if(l==1)
return0*
printf
("%s\n"
,x+1);
ll=l;
while
(ll>
1&&x[ll-1]
=='0'
)ll--
;memset
(vis,0,
sizeof
(vis));
for(
int i=l-
1;i>=
1;i--)}
for(
int i=
1;i<=len;i++
)printf
("\n");
}
洛谷P1415 拆分數列 解題思路
因為某些申必原因被刪除 題目描述 給出一列數字,需要你新增任意多個逗號將其拆成若干個嚴格遞增的數。如果有多組解,則輸出使得最後乙個數最小的同時,字典序最大的解 即先要滿足最後乙個數最小 如果有多組解,則使得第乙個數盡量大 如果仍有多組解,則使得第二個數盡量大,依次類推 輸入輸出格式 輸入格式 共一行...
洛谷 P1415 拆分數列 解題報告
為了響應 勤節儉 反鋪張的精神,題目背景描述故事部分略去 給出一列數字,需要你新增任意多個逗號將其拆成若干個嚴格遞增的數。如果有多組解,則輸出使得最後乙個數最小的同時,字典序最大的解 即先要滿足最後乙個數最小 如果有多組解,則使得第乙個數盡量大 如果仍有多組解,則使得第二個數盡量大,依次類推 共一行...
luoguP1415 拆分數列 dp
給出一列數字,需要你新增任意多個逗號將其拆成若干個嚴格遞增的數。如果有多組解,則輸出使得最後乙個數最小的同時,字典序最大的解 即先要滿足最後乙個數最小 如果有多組解,則使得第乙個數盡量大 如果仍有多組解,則使得第二個數盡量大,依次類推 輸入格式 共一行,為初始的數字。輸出格式 共一行,為拆分之後的數...