NOIP 2015 斗地主
2017-10-16 21:36
357 查看
题目描述
牛牛最近迷上了一种叫斗地主的扑克游戏。斗地主是一种使用黑桃、红心、梅花、方片的A到K加上大小王的共54张牌来进行的扑克牌游戏。在斗地主中,牌的大小关 系根据牌的数码表示如下: 3 < 4 < 5 < 6 < 7 < 8 < 9 < 10 < J < Q < K < A < 2 < 小王 < 大王 ,而花色并不对牌的大小产生影响。每一局游戏中,一副手牌由 nn 张牌组成。游戏者每次可以根据规定的牌型进行出牌,首先打光自己的手牌一方取得游戏的胜利。 现在,牛牛只想知道,对于自己的若干组手牌,分别最少需要多少次出牌可以将它们打光。请你帮他解决这个问题。
需要注意的是,本题中游戏者每次可以出手的牌型与一般的斗地主相似而略有不同。具体规则如下:
输入格式
第一行包含用空格隔开的2个正整数 T, n ,表示手牌的组数以及每组手牌的张数。接下来 T 组数据,每组数据 n 行,每行一个非负整数对 ai,bi,表示一张牌,其中 ai 表示牌的数码, bi 表示牌的花色,中间用空格隔开。特别的,我们用 1 来表示数码 A, 11 表示数码 J, 12 表示数码 Q, 13 表示数码 K;黑桃、红心、梅花、方片分别用 1-4 来表示;小王的表示方法为 0 1 ,大王的表示方法为 0 2 。
输出格式
共 T 行,每行一个整数,表示打光第 i 组手牌的最少次数。样例一
input
1 87 4
8 4
9 1
10 4
11 1
5 1
1 4
1 1
output
3explanation
共有 1 组手牌,包含 8 张牌:方片 7,方片 8,黑桃 9,方片 10,黑桃 J,黑桃 5,方片 A以及黑桃 A。可以通过打单顺子(方片 7,方片 8,黑桃 9,方片 10,黑桃 J),单张牌(黑桃 5)以及对子牌(黑桃 A以及方片 A)在 3 次内打光。样例二
input
1 1712 3
4 3
2 3
5 4
10 2
3 3
12 2
0 1
1 3
10 1
6 2
12 1
11 3
5 2
12 4
2 2
7 2
output
6题解:
暴搜+贪心根据经验,一般情况下先出顺子剩余的牌面会更少,而且顺子的选择也会影响我们牌面的组合,那我们贪心的思路就是先枚举如何出顺子,每次打完顺子之后,再去枚举四带x 三带x的情况,剩余的再按单牌,对牌出即可,与当前答案取最优情况更新即可。
注:四带二可以带大小王
代码
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn = 25; int a[maxn], num[maxn]; int n, t, ans; int solve() { memset(num, 0, sizeof(num)); for (int i = 0; i <= 13; i++) num[a[i]]++; int tot = 0; while (num[4] && num[2] > 1)//四带一对 { num[4] --; num[2] -= 2; tot ++; } while (num[4] && num[1] > 1)//四带两单 { num[4] --; num[1] -= 2; tot++; } while (num[4] && num[2]) { num[4] --; num[2] --; tot ++; } while (num[3] && num[2])//三带二 { num[3] --; num[2] --; tot ++; } while (num[3] && num[1])//三带一 { num[3] --; num[1] --; tot ++; } return tot + num[1] + num[2] + num[3] + num[4]; } void dfs(int x) { if (x >= ans) return; int nxt = solve(); if (nxt + x < ans) ans = nxt + x; for (int i = 2; i <= 13; i++)//三顺子 { int now = i; while (a[now] >= 3) now++; if (now - i >= 2) { for (int j = i + 1; j <= now - 1; j++) { for (int k = i; k <= j; k++) a[k] -= 3; dfs(x + 1); for (int k = i; k <= j; k++) a[k] += 3; } } } for (int i = 2; i <= 13; i++)//双顺子 { int now = i; while (a[now] >= 2) now++; if (now - i >= 3) { for (int j = i + 2; j <= now - 1; j++) { for (int k = i; k <= j; k++) a[k] -= 2; dfs(x + 1); for (int k = i; k <= j; k++) a[k] += 2; } } } for (int i = 2; i <= 13; i++)//单顺子 { int now = i; while (a[now] >= 1) now++; if (now - i >= 5) { for (int j = i + 4; j <= now - 1; j++) { for (int k = i; k <= j; k++) a[k]--; dfs(x + 1); for (int k = i; k <= j; k++) a[k]++; } } } } int main() { scanf("%d%d", &t, &n); while (t--) { memset(a, 0, sizeof(a)); for (int i = 1; i <= n; i++) { int x, y; scanf("%d%d", &x, &y); if (x == 1) x = 13; else if(x > 0) x --; a[x]++; } ans = 1e9; dfs(0); printf("%d\n", ans); } return 0; }
相关文章推荐
- NOIP 2015 斗地主
- 【NOIP2015】斗地主
- [NOIP2015] 斗地主
- [bzoj4325][NOIP2015]斗地主
- 洛谷P2668 斗地主(NOIp2015)(BZOJ4325)
- [NOIP2015]斗地主 搜索+贪心
- 【UOJ #147】【NOIP 2015】斗地主
- 【noip 2015】斗地主
- 4325. 【NOIP2015提高组Day1】斗地主
- BZOJ 4325: NOIP2015 斗地主 爆搜
- 【NOIP 2015】斗地主 贪心+迭代加深搜索
- UOJ 147 & 151 [NOIP2015]斗地主
- BZOJ 4325: NOIP2015 斗地主
- 斗地主 (NOIP2015 Day1 T3)
- 【NOIP】提高组2015 斗地主
- [NOIP2015] 提高组 洛谷P2668 斗地主
- noip2015 day1 斗地主
- NOIP2015 Day 1 T3 斗地主
- [NOIP2015] 斗地主 大爆搜
- NOIP 2015 [D1 T3]斗地主