P1415 拆分數列(記憶化搜尋)

2021-09-10 19:12:48 字數 2206 閱讀 4424

這麼麻煩的題敲出來沒wa真的是舒服~

原題:

題意:

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

解析:

大小比較函式:

int

compare

(int ll,

int rr,

int l,

int r)

return0;

}

第一要求最後乙個數最小,那麼先從後往前,得到乙個最小的滿足要求的段。這個段只要可以做到滿足要求,那麼答案段就是這個。(這個串的前面可能有字首0)

這個過程需要用到記憶化搜尋,即l~r這個區間可能被搜尋多次,如果這個區間不能達到要求,那麼標記-剪枝。

找到最後一段後,再要求前面的數大。那麼列舉從大開始,1~l-11~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

給出一列數字,需要你新增任意多個逗號將其拆成若干個嚴格遞增的數。如果有多組解,則輸出使得最後乙個數最小的同時,字典序最大的解 即先要滿足最後乙個數最小 如果有多組解,則使得第乙個數盡量大 如果仍有多組解,則使得第二個數盡量大,依次類推 輸入格式 共一行,為初始的數字。輸出格式 共一行,為拆分之後的數...