BashuOJ2963 數字遊戲 DFS 剪枝

2021-08-07 23:51:24 字數 1861 閱讀 1724

數字遊戲

題目大意:給定乙個

1 ~

n的排列

a ,每次將相鄰兩項相加,構成新的序列,例如經過一次操作後變為,可以知道每次序列的長度都會減1,最後會得到乙個整數su

m,現在給你這個su

m ,請求出一開始的排列

a ,要求字典序最小。

做法:本題需要使用dfs+剪枝來解決。

首先我們思考,什麼樣的排列可以使最後的整數等於su

m。我們把a1

,a2,

...,

an作為未知數計算最後整數的值,可以發現,最後得到的式子中,ai

項的係數恰是楊輝三角形中第

n 層的第

i個數,具體就不證明了。那麼這樣我們就可以根據排列來算最後的整數了。

列舉所有排列是o(

n!) 的,然而本題中

n 最大為20,需要考慮剪枝。在這裡我們需要用到乙個叫做排序不等式的東西,具體來說,設x1

≤x2≤

...≤

xn,y

1≤y2

≤...

≤yn ,要將這兩個數列中的數字一一配對,那麼最後每對數的乘積之和大於等於x1

yn+x

2yn−

1+..

.+xn

y1且小於等於x1

y1+x

2y2+

...+

xnyn

。那麼這個東西於這道題來說有什麼用呢?在搜尋的時候,我們知道剩下的還沒選的數字,還知道要和它們配對的係數,那麼我們就可以求出它們配對後的和的最大值和最小值,如果目前的和加上這個最大值仍然趕不上su

m ,那麼就不用繼續搜下去了,同理,如果目前的和加上最小值已經比su

m 大,也不用繼續搜下去了。

這樣剪枝後,還剩下兩個測試點tle,怎麼辦呢?我們知道,楊輝三角中每一層的數都是左右對稱的,所以對於乙個排列,如果它可行,那麼調換對稱的兩個位置上的數,它也是可行解。反之,如果它不是可行解,那麼調換過來也不可能是可行解。這就給我們提供了剪枝的思路:對於現在列舉到的一位,如果它處於後半部分,那麼它如果小於前面和它對稱位置上選擇的數,是不可能找到可行解的。採取反證法,如果這樣找到了可行解,那麼調換這兩位可以找到乙個字典序更小的解,然而之前並沒有找到這樣的解,所以這種情況下不可能找到可行解,就可以剪掉了。再加入這個剪枝後就可以ac了。

以下是本人**:

#include 

#include

#include

#include

#include

using

namespace

std;

int n,sum,ans[25]=,c[25][25]=;

bool vis[25]=;

void solve(int step,int &maxx,int &minx)

if (!ans[n-i]&&n-i>i+1)

}}bool dfs(int step,int now)

else

return

0; }

int maxx,minx;

solve(step,maxx,minx);

if (now+maxxreturn

0; if (now+minx>sum) return

0; int i=1;

if (step>n-step+1) i=ans[n-step+1]+1;

for(;i<=n;i++)

if (!vis[i])

return0;}

int main()

數字DP 數字遊戲

科協裡最近很流行數字遊戲。某人命名了一種不降數,這種數字必須滿足從左到右個位數字呈現小於等於的關係,如123,446.現在大家決定玩乙個遊戲,指定乙個整數閉區間 a,b 問這個區間內有多少個不降數。輸入多組測試資料。每組只包含兩個數字a和b 1 a,b 2 31 每行給出乙個測試資料的答案,即 a,...

數字DP 數字遊戲

科協裡最近很流行數字遊戲。某人命名了一種不降數,這種數字必須滿足從左到右各位數字呈非下降關係,如 123,446。現在大家決定玩乙個遊戲,指定乙個整數閉區間 a,b 問這個區間內有多少個不降數。輸入格式 輸入包含多組測試資料。每組資料佔一行,包含兩個整數 a 和 b。輸出格式 每行給出一組測試資料的...

數字遊戲題解

題目描述 丁丁最近沉迷於乙個數字遊戲之中。這個遊戲看似簡單,但丁丁在研究了許多天之後卻發覺原來在簡單的規則下想要贏得這個遊戲並不那麼容易。遊戲是這樣的,在你面前有一圈整數 一共n個 你要按順序將其分為m個部分,各部分內的數字相加,相加所得的m個結果對10取模後再相乘,最終得到乙個數k。遊戲的要求是使...