HDU - 3391 C - Mahjong
题意:如果摸到的14张麻将,可以组成4副三张麻将连续或者相同的,以及两个一样的就能获胜。
思路:直接暴力枚举每种可以摸到的牌型,用dfs判断当前拿到的14张牌型能否获胜。
如果搜索时不优化会超时,如果你选择了第cur张牌,那么你下次不必再选择cur以前的牌,因为会造成重复搜索。加上这个剪枝就能过掉。我还自己加了一个剪枝:先排序,然后如果组合到第cur张牌,前面还有牌没有组合,说明不可能组合完,因为每张牌只会和它自身以及比它更大的牌组合。
字符的处理:s、b、c看做0,1,2,那么1s就表示10,5b表示51,就能愉快地转换成数字了。
AC代码:78ms
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <utility>
#include <string>
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
#define eps 1e-10
#define inf 0x3f3f3f3f
#define PI pair<int, int>
typedef long long LL;
const int maxn = 100+5;
char p[] = {'s', 'b', 'c'};
int vis[maxn], cnt[maxn], a[20];
bool dfs(int k, int cur) {
for(int i = 0; i < cur; ++i) { //剪枝
if(cnt[a[i]]) return false;
}
if(k == 5) return true;
if(k == 0) {
for(int i = 0; i < 14; ++i) {
int x = a[i];
if(cnt[x] >= 2 && !vis[x]) {
vis[x] = 1;
cnt[x] -= 2;
if(dfs(k+1, cur)) return true;
cnt[x] += 2;
}
}
}
else {
for(int i = cur; i < 14; ++i) {
int x = a[i];
//取三个一样的
if(cnt[x] >= 3) {
cnt[x] -= 3;
if(dfs(k+1, i)) return true;
cnt[x] += 3;
}
//取三个连续的
int y = x / 10, z = x % 10;
if(y + 2 <= 9) {
int flag = 1;
for(int j = 0; j < 3; ++j) {
if(!cnt[(y+j)*10+z]) {
flag = 0;
break;
}
}
if(flag) {
for(int j = 0; j < 3; ++j) cnt[(y+j)*10+z]--;
if(dfs(k+1, i)) return true;
for(int j = 0; j < 3; ++j) cnt[(y+j)*10+z]++;
}
}
}
}
return false;
}
int main() {
char ma[5];
int T, kase = 1;
scanf("%d", &T);
while(T--) {
memset(cnt, 0, sizeof(cnt));
for(int i = 0; i < 13; ++i) {
scanf("%s", ma);
for(int j = 0; j < 3; ++j) {
if(ma[1] == p[j]) {
a[i] = (ma[0]-'0')*10+j;
cnt[a[i]]++;
}
}
}
int old[maxn] , b[maxn];
memcpy(old, cnt, sizeof(cnt));
memcpy(b, a, sizeof(a));
printf("Case %d:", kase++);
int ans = 0;
for(int i = 0; i <= 2; ++i)
for(int j = 1; j <= 9; ++j) {
int x = j * 10 + i;
if(cnt[x] == 4) continue;
memset(vis, 0, sizeof(vis));
memcpy(cnt, old, sizeof(old));
memcpy(a, b, sizeof(a));
a[13] = x;
sort(a, a+14);
cnt[x]++;
if(dfs(0, 0)) {
++ans;
printf(" %d%c", j, p[i]);
}
}
if(!ans) printf(" None");
printf("\n");
}
return 0;
}
如有不当之处欢迎指出!
HDU - 3391 C - Mahjong的更多相关文章
- HDU 5379 Mahjong tree(dfs)
题目链接:pid=5379">http://acm.hdu.edu.cn/showproblem.php? pid=5379 Problem Description Little su ...
- HDU 5379 Mahjong tree(树的遍历&组合数学)
本文纯属原创,转载请注明出处.谢谢. http://blog.csdn.net/zip_fan 题目传送门:http://acm.hdu.edu.cn/showproblem.php? pid=537 ...
- Hdu 5379 Mahjong tree (dfs + 组合数)
题目链接: Hdu 5379 Mahjong tree 题目描述: 给出一个有n个节点的树,以节点1为根节点.问在满足兄弟节点连续 以及 子树包含节点连续 的条件下,有多少种编号方案给树上的n个点编号 ...
- HDU 4431 Mahjong (DFS,暴力枚举,剪枝)
题意:给定 13 张麻将牌,问你是不是“听”牌,如果是输出“听”哪张. 析:这个题,很明显的暴力,就是在原来的基础上再放上一张牌,看看是不是能胡,想法很简单,也比较好实现,结果就是TLE,一直TLE, ...
- 2015多校第7场 HDU 5379 Mahjong tree 构造,DFS
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5379 题意:一颗n个节点n-1条边的树,现在要给每个节点标号(1~n),要求:(1)每一层的兄弟节点的 ...
- HDU 4431 Mahjong(枚举+模拟)(2012 Asia Tianjin Regional Contest)
Problem Description Japanese Mahjong is a four-player game. The game needs four people to sit around ...
- HDU 5379——Mahjong tree——————【搜索】
Mahjong tree Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Tota ...
- 2015 Multi-University Training Contest 7 hdu 5379 Mahjong tree
Mahjong tree Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Tota ...
- HDU 4431 Mahjong 模拟
http://acm.hdu.edu.cn/showproblem.php?pid=4431 不能说是水题了,具体实现还是很恶心的...几乎优化到哭但是DFS(还加了几个剪枝)还是不行...搜索一直T ...
随机推荐
- linkin大话数据结构--Set
Set 集合 Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个 Set 集合中,则添加操作失败. Set 判断两个对象是否相同不是使用 == 运算符,而是根据 equals 方法.也 ...
- pulltorefresh 设置刷新文字提示颜色
xmlns:ptr="http://schemas.android.com/apk/res-auto" 赵泽民 2016/7/12 15:48:58 ptr:ptrHeaderS ...
- javascript 中的console.log有什么作用啊?
相比alert他的优点是: 他能看到结构话的东西,如果是alert,淡出一个对象就是[object object],但是console能看到对象的内容. console不会打断你页面的操作,如果用al ...
- Angular之ngRoute与uiRoute
ngRoute不支持嵌套路由 用法如下: <!DOCTYPE html> <html lang="en" ng-app="myApp"> ...
- awk打印第n个参数到最后一个技巧/将n行组成一列
打印第n参数到最后一个参数 文本的NF不等,即字段长度不固定,想截取从$3到$NF 第一反应是使用循环 [root@localhost ~]# echo "1 2 3 4 5" | ...
- 13 Basic Cat Command Examples in Linux(转) Linux中cat命令的13中基本用法
Cat (串联) 命令是Linux/Unix开源系统中比较常用的一个命令.我们可以通过Cat命令创建一个或多个文件,查看文件内容,串联文件并将内容输出到终端设备或新的文件当中,这篇文章我们将会以实例的 ...
- Python selenium 一个节点两个关联input
HTML代码: 一个节点两个关联input 多出现于密码框 先需要模拟点击进入第一个input,才能激活第二个input. 代码: driver.find_element_by_name('Text ...
- Jmeter之性能压测Stepping Thread Group 逐步增加并发数 阶梯式加压并发 (十五)
前段时间有描述过性能的测试类型 配置负载 Big Bang: 负载同时产生 Ramp up: 开始时候产生一定负载,然后每隔一段时间增加一些负载直到达到目标负载,这是典型模式 Ramp-up (wit ...
- 07_Python变量内存地址、小数据池
一.变量在内存中的地址 变量:用来标识(identify)一块内存区域.为了方便表示内存,我们操作变量实质上是在操作变量指向的那块内存单元.编译器负责分配.我们可以使用Python内建函数id()来获 ...
- kali初探:root用户打开wireshark打开失败
启动wireshark后,报错: 该界面提示在init.lua文件中使用dofile函数禁用了使用超级用户运行wireshark.这是因为wireshark工具是使用Lua语言编写的,并且在kali ...