牛牛最近迷上了一種叫鬥地主的撲克遊戲。鬥地主是一種使用黑桃、紅心、梅花、方片的 $ a $ 到 $ k $ 加上大小王的共 $ 54 $ 張牌來進行的撲克牌遊戲。在鬥地主中,牌的大小關係根據牌的數碼表示如下:$ 3 < 4 < 5 < 6 < 7 < 8 < 9 < 1 0 < j < q < k < a < 2 < $ 小王 $ < $ 大王,而花色並不對牌的大小產生影響。每一局遊戲中,一副手牌由 $ n $ 張牌組成。遊戲者每次可以根據規定的牌型進行出牌,首先打光自己的手牌一方取得遊戲的勝利。
現在,牛牛只想知道,對於自己的若干組手牌,分別最少需要多少次出牌可以將它們打光。
需要注意的是,本題中遊戲者每次可以出手的牌型與一般的鬥地主相似而略有不同。具體規則如下:
另外,在順牌(單順子、雙順子、三順子)中,牌的花色不要求相同。
第一行包含用空格隔開的 $ 2 $ 個正整數 $ t \(,\) n $,表示手牌的組數以及每組手牌的張數。
接下來 $ t $ 組資料,每組資料 $ n $ 行,每行乙個非負整數對 $ a_i, b_i $,表示一張牌,其中 $ a_i $ 表示牌的數碼,$ b_i $ 表示牌的花色,中間用空格隔開。特別的,我們用 $ 1 $ 來表示數碼 $ a \(,\) 11 $ 表示數碼 $ j \(,\) 12 $ 表示數碼 $ q \(,\) 13 $ 表示數碼 $ k $;黑桃、紅心、梅花、方片分別用 $ 1 - 4 $ 來表示;小王的表示方法為0 1
,大王的表示方法為0 2
。
共 $ t $ 行,每行乙個整數,表示打光第 $ i $ 組手牌的最少次數。
看到這麼小的資料範圍,應該一眼就能想到狀壓dp搜尋。
的確,這是一道非常裸的搜尋題。
直接暴力搜尋即可。
哇我這麼快就切了一道藍題
這樣想你就太天真了。
提交後發現,這樣做只會得到\(30\)分。
為什麼呢?讓我們分析一下原因:
我們每一次都列舉了所有可行的狀態,冗餘狀態太多。
會搜一些對題目答案沒有任何影響的狀態。
其實這樣的根本原因就是:沒有乙個搜尋的順序。
按照正常的打牌者的角度去思考,你會發現:我們每一次都是先出順子,在考慮帶牌,最後才是單牌/炸彈/對子。
我們這樣去搜尋就可以\(\mathrm\)。
但是,你還會發現乙個新問題:如果拆牌打所需次數更少呢?
可以看到最後一句話:資料保證:所有的手牌都是隨機生成的。
而我們在打牌時很少會有拆牌方案更好的情況。
那麼出現這個問題的機率就微乎其微了。
這個題的資料經過了特殊構造,可以卡掉沒有考慮拆牌方案的做法。
我太懶了,沒有考慮拆牌的情況qwq
/********************************
author: csxsl
date: 2019/10/28
language: c++
problem: p2668
********************************/
#include #define itn int
#define gi gi
using namespace std;
inline int gi()
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return f * x;
}inline long long gl()
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return f * x;
}int t, n, a[25], ans;
void dfs(int now)//搜尋主過程
} }//雙順子
ps = 0;//記得清零對數
for (int i = 3; i <= 14; i+=1)//列舉3~a
}} //三順子
ps = 0;//清零對數
for (int i = 3; i <= 14; i+=1)//列舉3~a
}}
//考慮帶牌的情況
for (int i = 2; i <= 14; i+=1)//列舉2~a,因為2也可以進行帶牌
//三帶二
for (int j = 2; j <= 14; j+=1)//列舉2~a
a[i] += 3;//回溯加上三張牌
} else //可以選擇三帶
一、三帶二或四帶二
//三帶二同理
for (int j = 2; j <= 14; j+=1)
a[i] += 3;
//四帶二
a[i] -= 4;
//帶兩張單牌
for (int j = 2; j <= 15; j+=1)//先從 2~大小王 列舉第一張單牌
++a[j];//那會那一張牌
}//帶兩對對子
for (int j = 2; j <= 14; j+=1)//列舉第一對
a[j] += 2;
}a[i] += 4;//加上出的4張牌
} }//單牌/炸彈/對子 最後考慮,因為它們都可以一次出完
for (int i = 2; i <= 15; i+=1) if (a[i]) ++now;
ans = min(ans, now);//更新答案
return;//返回
}int main()
dfs(0);//進行搜尋
printf("%d\n", ans);//輸出答案
} return 0;
}
可以發現,我們每次輸入的花色並沒有任何用處。
因此,題目中輸入的資料/給出的條件,並不一定都是有用的。
NOIP2015 鬥地主 洛谷P2668
題目描述 牛牛最近迷上了一種叫鬥地主的撲克遊戲。鬥地主是一種使用黑桃 紅心 梅花 方片的a到k加上大小王的共54張牌來進行的撲克牌遊戲。在鬥地主中,牌的大小關係根據牌的數碼表示如下 3 4 5 6 7 8 9 10 include include include using namespace st...
洛谷 P2668 鬥地主
牛牛最近迷上了一種叫鬥地主的撲克遊戲。鬥地主是一種使用黑桃 紅心 梅花 方片的a到k加上大小王的共54張牌來進行的撲克牌遊戲。在鬥地主中,牌的大小關係根據牌的數碼表示如下 3 4 5 6 7 8 9 10現在,牛牛只想知道,對於自己的若干組手牌,分別最少需要多少次出牌可以將它們打光。請你幫他解決這個...
洛谷P2668 鬥地主
牛牛最近迷上了一種叫鬥地主的撲克遊戲。鬥地主是一種使用黑桃 紅心 梅花 方片的 a 到 k 加上大小王的共 54 張牌來進行的撲克牌遊戲。在鬥地主中,牌的大小關 系根據牌的數碼表示如下 3 4 5 6 7 8 9 10,而花色並不對牌的大小產生影響。每一局遊戲中,一副手牌由 n 張牌組成。遊戲者每次...