題解 洛谷P2668 NOIP2015 鬥地主

2022-07-02 17:12:12 字數 3401 閱讀 8720

牛牛最近迷上了一種叫鬥地主的撲克遊戲。鬥地主是一種使用黑桃、紅心、梅花、方片的 $ 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 張牌組成。遊戲者每次...