NOIP2015 斗地主 (搜索剪枝)
2017-10-15 10:33
435 查看
Description
牛牛最近迷上了一种叫斗地主的扑克游戏。斗地主是一种使用黑桃、红心、梅花、方片的A到K加上大小王的共54张牌来进行的扑克牌游戏。在斗地主中,牌的大小关系根据牌的数码表示如下:3<4<5<6<7<8<9<10<J<Q<K<A<2<小王<大王,而花色并不对牌的大小产生影响。每一局游戏中,一副手牌由n张牌组成。游戏者每次可以根据规定的牌型进行出牌,首先打光自己的手牌一方取得游戏的胜利。现在,牛牛只想知道,对于自己的若干组手牌,分别最少需要多少次出牌可以将它们打光。请你帮他解决这个问题。
需要注意的是,本题中游戏者每次可以出手的牌型与一般的斗地主相似而略有不同。具体规则如下:
![](https://cdn.luogu.org/upload/pic/1827.png)
Solution
考虑爆搜,先搜索顺子,在去检查所有的四带二,三带一,三带二,对子,单子即可。Code
#include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<iostream> #include<algorithm> #include<queue> #include<vector> #include<set> #define For(i , j , k) for (register int i = (j) , _##end_ = (k) ; i <= _##end_ ; ++ i) #define Fordown(i , j , k) for (register int i = (j) , _##end_ = (k) ; i >= _##end_ ; -- i) #define Set(a , b) memset(a , b , sizeof(a)) #define pb push_back #define INF (0x3f3f3f3f) #define Mod (1000000007) using namespace std; typedef long long LL; template <typename T> inline bool chkmax(T &a , T b) { return a < b ? (a = b , 1) : 0; } template <typename T> inline bool chkmin(T &a , T b) { return b < a ? (a = b , 1) : 0; } int _ , __; char c_; inline int read() { for (_ = 0 , __ = 1 , c_ = getchar() ; !isdigit(c_) ; c_ = getchar()) if (c_ == '-') __ = -1; for ( ; isdigit(c_) ; c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48); return _ * __; } inline void file() { #ifdef hany01 freopen("ddz.in" , "r" , stdin); freopen("ddz.out" , "w" , stdout); #endif } int n , T , num_ , col_ , cnt[20] , Ans , cnt_[6]; void calc(int cur) { int sum = 0; Set(cnt_ , 0); For(i , 0 , 14) ++ cnt_[cnt[i]]; while (cnt_[4] && cnt_[2] > 1) -- cnt_[4], cnt_[2] -= 2, ++ sum; while (cnt_[4] && cnt_[1] > 1) -- cnt_[4], cnt_[1] -= 2, ++ sum; while (cnt_[4] > 1) cnt_[4] -= 2, ++ sum; while (cnt_[3] && cnt_[2]) -- cnt_[3], -- cnt_[2], ++ sum; // cout << sum << endl; // cout << cnt_[3] << ' ' << cnt_[1] << endl; while (cnt_[3] && cnt_[1]) -- cnt_[3], -- cnt_[1], ++ sum; // cout << sum << endl; // cout << sum + cnt_[1] + cnt_[2] + cnt_[3] + cnt_[4] + cur << endl; // cout << "-----华丽的分割线------" << endl; chkmin(Ans , sum + cnt_[1] + cnt_[2] + cnt_[3] + cnt_[4] + cur); } void dfs(int cur) { if (cur > Ans) return; calc(cur); int beg_ , end_; beg_ = 3; end_ = 2; For(i , 3 , 14) { if (cnt[i]) ++ end_; else { For(ii , beg_ , end_) For(jj , ii + 4 , end_) { For(j , ii , jj) -- cnt[j]; dfs(cur + 1); For(j , ii , jj) ++ cnt[j]; } beg_ = i + 1; end_ = i; } } For(ii , beg_ , end_) For(jj , ii + 4 , end_) { For(j , ii , jj) -- cnt[j]; dfs(cur + 1); For(j , ii , jj) ++ cnt[j]; } beg_ = 3; end_ = 2; For(i , 3 , 14) { if (cnt[i] >= 2) ++ end_; else { For(ii , beg_ , end_) For(jj , ii + 2 , end_) { For(j , ii , jj) cnt[j] -= 2; dfs(cur + 1); For(j , ii , jj) cnt[j] += 2; } beg_ = i + 1; end_ = i; } } For(ii , beg_ , end_) For(jj , ii + 2 , end_) { For(j , ii , jj) cnt[j] -= 2; dfs(cur + 1); For(j , ii , jj) cnt[j] += 2; } beg_ = 3; end_ = 2; For(i , 3 , 14) { if (cnt[i] >= 3) ++ end_; else { For(ii , beg_ , end_) For(jj , ii + 1 , end_) { For(j , ii , jj) cnt[j] -= 3; dfs(cur + 1); For(j , ii , jj) cnt[j] += 3; } beg_ = i + 1; end_ = i; } } For(ii , beg_ , end_) For(jj , ii + 1 , end_) { For(j , ii , jj) cnt[j] -= 3; dfs(cur + 1); For(j , ii , jj) cnt[j] += 3; } } int main() { file(); T = read(); n = read(); while (T --) { Set(cnt , 0); For(i , 1 , n) { num_ = read(); col_ = read(); if (num_ == 1) num_ = 14; ++ cnt[num_]; } Ans = INF; dfs(0); printf("%d\n" , Ans); } return 0; }
相关文章推荐
- [noip2015]斗地主(dfs+贪心)
- NOIP 2015 提高组 Day1 斗地主
- (noip 2015 斗地主)<搜索+贪心>
- noip2015 day1 斗地主
- [noip2015]斗地主 题解
- [NOIP2015] 斗地主 大爆搜
- C++——NOIP2015提高组day1 t3——斗地主
- Noip2015 Day1 T3 斗地主(Dfs+Dp优化)
- noip2015 斗地主
- 【uoj147】NOIP2015—斗地主
- [NOIP 2015] 斗地主 landlord
- 【NOIP2015】斗地主
- 2106. [NOIP2015] 斗地主
- UOJ #151. 【NOIP2015】斗地主“加强”版【搜索+贪心
- NOIP2015 斗地主 洛谷P2668
- NOIP 2015 D1 T3 斗地主(特详细讲解)
- [NOIP2015]斗地主
- UOJ147 [NOIP2015]斗地主 解题报告【搜索】【贪心】
- Luogu 2668 NOIP 2015 斗地主(搜索,动态规划)
- 【BZOJ4325】【NOIP2015】斗地主 搜索