給你一副手牌,沒有飛機帶翅膀,按鬥地主的規則,求將所有牌打出的最少次數。
我們已經知道花色對牌沒有影響,那麼如果不考慮順子,每個牌具體是什麼數字我們也用不著知道,我們關心的只有牌堆中單張、對子、棒子、炸彈、王的個數。因此我們可以用$f(k_1,k_2,k_3,k_4,k_x)$表示當有$k_1$個單張,$k_2$個對子,$k_3$個棒,$k_4$個炸彈,$k_x$個王時,將牌全部打出的最少次數。而顯然這是可以進行dp的。轉移方式為:要麼不拆牌而出牌,要麼拆牌。
看以下拆牌的遞推式:
if (k2)//將二拆成兩個單張updmin(cur, f[k1 + 2][k2 - 1][k3][k4][kx]);
if (k3)//將三拆成乙個單張和一對
updmin(cur, f[k1 + 1][k2 + 1][k3 - 1][k4][kx]);
if (k4)//將四拆成乙個單張和一棒
updmin(cur, f[k1 + 1][k2][k3 + 1][k4 - 1][kx]);
if (k4)//將四拆成兩對
updmin(cur, f[k1][k2 + 2][k3][k4 - 1][kx]);
我們從外到裡考慮。最外層不可以從+1處轉移,因此我們把$k_4$選為最外層。此時,從$k_4-1$處的轉移就都合法了,我們看從$k_4$轉移時,第二層不可以從+1處轉移。故第二層選$k_3$。此時,從$k3-1$處的轉移就都合法了。當從$k_3$處轉移時,第三層不可以從+1處轉移……因此,遞推順序為$k_4\rightarrow k_3\rightarrow k_2\rightarrow k_1\rightarrow k_x$。
列舉所有出順子的方式(暴力搜順子),然後再在剩餘的牌中查dp表即可。
#include #include #include #include using namespace std;#define updmin(x, y) x = min(x, y)
const int max_id = 27, max_idcnt = 7, inf = 0x3f3f3f3f;
const int idbegin = 1, idshunziend = 12, idlast = 13, maxunitlen = 3;
const int unitcnt[4] = ;
int f[max_id][max_id][max_id][max_id][max_id];
int idcnt[max_id], idcnt_cnt[max_idcnt];
int cardcnt, ans;
void doshunzi(int shunzicnt, int idbegin, int unitlen, int unitcnt)
void dp()
}int main()
doshunzi(0, 0, 0, 0);
printf("%d\n", ans);
}return 0;
}
P2540 鬥地主增強版
p2540鬥地主增強版 參考大佬題解 思路 順子暴力搜,剩下的牌我不會貪心所以用記憶化搜尋 或者dp 注意 雙王不能當對,二不算順子 1 include 2 include 3 include 4 include 5 include 6 using namespace std 78 define r...
15 鬥地主案例 雙列
鬥地主綜合案例 有序版本 1.準備牌 特殊牌 大王,小王 52張牌 迴圈巢狀遍歷兩個集合 或陣列 組成成52張牌 listcolors new arraylist listnumbers new arraylist collections.addall colors,collections.adda...
拖三鬥地主遊戲介紹
拖三鬥地主是以三人鬥地主為基礎,融入安徽宿松的拖三玩法,增加了遊戲的趣味性和複雜度。與三人鬥地主的主要差別 1 新增炸彈 5 10 k各一張 純龍 同花色的順子 四個或更多的連對 不包括2和王 通天龍 3到a的順子 其中510k和通天龍都包括一般和純色兩種。2 炸彈比較 基本原則是張數越多,炸彈越大...