如何計算排列方法數,其中相同元素不能相鄰?

時間 2021-06-01 02:31:42

1樓:王贇 Maigo

匿名使用者的動態規劃解法是正解,不過直接看程式不容易看懂,我來用人話解釋一遍。

首先澄清一點題意:從題主的描述來看,相同的數交換位置算同一種擺法。不過從匿名使用者的程式來看,題目是以撲克牌為背景的,點數相同的牌還有花色的區別。我就按後一種題意來講了。

先來設計一種樸素的狀態:用表示還剩下張1、張2、……、張n需要擺放。

考慮到不允許相同的數字相鄰,還需要在狀態中補充乙個數k,表示第一張牌不能是k點(以下稱k為「禁手」)。

這樣,乙個狀態對應的擺法數就是:

0}} a_i \cdot C(a_1, a_2, \cdots, a_i - 1, \cdots, a_n, i)" eeimg="1"/>

這裡的下標i就列舉了第一張牌是幾點,它不能取k,也不能取已經一張不剩的牌。第一張牌選了i點後,下一張牌的「禁手」就變成i了。

動態規劃的初始條件是(禁手是幾都無所謂),

而待求的擺法數是(0表示無禁手)。

這種狀態設計方法能夠解決問題,但明顯有大量的冗餘狀態:

把狀態中的各個交換(若涉及禁手,則也要做相應調整),擺法數是一樣的。

其實,狀態中每種牌還剩幾張並不重要,重要的是有幾種牌還剩1張、有幾種牌還剩2張……等等。

所以我們把狀態修改成這樣:用表示還有種牌剩餘1張,種牌剩餘2張,……,種牌剩餘m張,禁手牌剩餘k張。m取各的最大值就夠了。

這樣,狀態轉移方程就變成了:

\delta_}} (b_i - \delta_) \cdot i \cdot C(b_1, b_2, \cdots, b_ + 1, b_i - 1, \cdots, b_m, i-1) " eeimg="1"/>

這裡下標i表示選擇一種還剩i張的牌。定義在i=k時取1,否則取0。求和式中的第一項表示有種牌可選(若禁手牌恰也剩餘i張,則少一種);第二項i表示每種牌有i張不同花色可選;第三項是轉移後的狀態——剩餘i張的牌少了一種,而剩餘i-1張的牌多了一種,同時禁手牌(即剛剛選的牌)剩餘i-1張。

初始條件是仍是,待求狀態無禁手。

在實際程式設計的時候,為了保證僅計算有用的狀態,可以用記憶化搜尋實現。

若不計不同花色的區別,只需去掉第乙個狀態轉移方程右邊的,或第二個狀態轉移方程右邊的i。

2樓:

程式設計之美那個題可以用dp來做。

#include

#include

using

namespace

std;

unsigned

long

longdp[

14][

14][

14][

14][5];

bool

cal[

14][

14][

14][

14][5];

// b[x] 表示的是還有b[x]種牌還剩x張, forbid表示的禁手牌還剩下的數量

unsigned

long

long

get_dp

(int(&

b)[5],

intforbid

)// 標記為計算過

Cal=

true

;// Dp初始為0Dp=

0;// 記錄是否還有牌

bool

hascard

=false

;// 新的計數

intnewb[5

];// 列舉相同面值剩餘數目是 i

for(

inti=1

;i<=4;

i++)// 如果沒卡,應該特殊處理為1,初始狀態if(!hascard

)returnDp;

}int

main

()elseif(

p=='T')

elseif(

p=='J')

elseif(

p=='Q')

elseif(

p=='K')

else

cin>>p;

}int

newb[5

];memset

(newb,0

,sizeof

(newb

));for

(inti=

0;i<13;

i++)cout

<<"Case #"

<

": "

<

(newb,0

)<

乙個重新排列的演算法,如何計算每種排列的概率?

Ryan Lee 貼兩個老鏈結,雖然提的這個問題是原問題的子問題,但分析裡也解釋的很清楚了。 sniperelite 一種方法當然是首先弄乙個數池,池中有1 n的數字,然後每次以等概率選出乙個並從池中移除。另外MATLAB的randperm提供了乙個巧妙的思路 隨機產生n個均勻分布的隨機數,並且依次...

如何用程式語言實現三相配平計算?

水牛 你是要自動在AutoCAD裡排迴路相序吧。個人覺得,搞這麼複雜沒必要吧。因為一方面,雖然程式設計可以根據輸入的計算電流給出優化的相序組合方案,但這樣子的結果肯定是相序無規律的,配電箱中就會出現一排開關所接相序完全混亂無規律的現象,對配電箱的生產和檢修都不利。而一般情況下,配電箱都是按A,B,C...

圍棋普遍的判定勝負的方法是什麼?如何計算目數?

圖1.停留在棋盤上的棋子誰多誰贏。圍棋勝負規則,非常簡單,只是有時候聽起來很難。最核心的思想 最後停留在棋盤上的棋子誰多誰贏。如圖1,數一數,黑棋比白棋多,黑棋贏。圖2.無需走到填滿棋盤 後來,人們發現,填滿棋盤太蠢了,其實圍到雙方棋子都接觸,剩下的空點,對方走進去一定會被吃掉時,這些所圍空點也是我...