#####枚举
import java.io.*;
import java.util.*; public class Main { static HashSet<String> set1;
static HashSet<String> set2;
static HashSet<String> set3;
static Map<String, Integer> occuredTimes;
static HashSet<String> set4; static HashSet<String> set5;
static Map<String, Map<String, Integer>> cmpMap = new HashMap<>();
static Comparator<String> cmp;
static String[] tiles; static int[] m9;
static int[] s9;
static int[] p9;
static int[] c7; static int[] sum; static List<String[][]>[] m9Collections = new ArrayList[3];
static List<String[][]>[] s9Collections = new ArrayList[3];
static List<String[][]>[] p9Collections = new ArrayList[3];
static List<String[][]>[] c7Collections = new ArrayList[3]; public static List<String> judge1() {
Arrays.sort(Main.tiles, cmp); char[] op = new char[]{'m', 's', 'p', 'c'}; String[][] collection = new String[4][3]; if (sum[0] >= 3) {
for (int min = getMin(sum[0]); min <= Math.min(sum[0] / 3, 3); min++) {
int[] tmp = Arrays.copyOf(m9, m9.length);
dfs(m9, 'm', 0, 0, collection, min);
m9 = tmp;
}
}
if (sum[1] >= 3) {
for (int min = getMin(sum[1]); min <= Math.min(sum[1] / 3, 3); min++) {
int[] tmp = Arrays.copyOf(s9, s9.length);
dfs(s9, 's', 0, 0, collection, min);
s9 = tmp;
}
}
if (sum[2] >= 3) {
for (int min = getMin(sum[2]); min <= Math.min(sum[2] / 3, 3); min++) {
int[] tmp = Arrays.copyOf(p9, p9.length);
dfs(p9, 'p', 0, 0, collection, min);
p9 = tmp;
}
}
if (sum[3] >= 3) {
for (int min = getMin(sum[3]); min <= Math.min(sum[3] / 3, 3); min++) {
int[] tmp = Arrays.copyOf(c7, c7.length);
dfs(c7, 'c', 0, 0, collection, min);
c7 = tmp;
}
} //3个的集合
List<String[][]>[] allSet3 = new List[]{m9Collections[2], s9Collections[2], p9Collections[2], c7Collections[2]}; HashSet<String> ans = new HashSet<>();
for (List<String[][]> set : allSet3) {
for (String[][] coll : set) {
//把剩下的4个找出来
Map<String, Integer> amp = new HashMap<>();
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
amp.put(coll[i][j], amp.getOrDefault(coll[i][j], 0) + 1);
}
}
processLeft(ans, amp);
}
}
List<String[][]>[] allSet2 = new List[]{m9Collections[1], s9Collections[1], p9Collections[1], c7Collections[1]};
List<String[][]>[] allSet1 = new List[]{m9Collections[0], s9Collections[0], p9Collections[0], c7Collections[0]};
//处理第2,1;
for (int i = 0; i < 4; i++) {
List<String[][]> set = allSet2[i];
for (String[][] coll : set) {
for (int j = 0; j < 4; j++) {
if (j != i) {
List<String[][]> set2 = allSet1[j];
for (String[][] coll2 : set2) {
Map<String, Integer> amp = new HashMap<>();
for (int ii = 0; ii < 2; ii++) {
for (int jj = 0; jj < 3; jj++) {
amp.put(coll[ii][jj], amp.getOrDefault(coll[ii][jj], 0) + 1);
}
} for (int jj = 0; jj < 3; jj++) {
amp.put(coll2[0][jj], amp.getOrDefault(coll2[0][jj], 0) + 1);
} processLeft(ans, amp);
}
}
}
}
}
//处理3个1的场景
dealList(m9Collections[0], s9Collections[0], p9Collections[0], ans);
dealList(m9Collections[0], s9Collections[0], c7Collections[0], ans);
dealList(m9Collections[0], p9Collections[0], c7Collections[0], ans);
dealList(s9Collections[0], p9Collections[0], c7Collections[0], ans); return new ArrayList<>(ans);
} public static void dealList(List<String[][]> collect1, List<String[][]> collect2, List<String[][]> collect3, HashSet<String> ans) {
for (String[][] set1 : collect1) {
for (String[][] set2 : collect2) {
for (String[][] set3 : collect3) {
Map<String, Integer> amp = new HashMap<>(); for (int jj = 0; jj < 3; jj++) {
amp.put(set1[0][jj], amp.getOrDefault(set1[0][jj], 0) + 1);
} for (int jj = 0; jj < 3; jj++) {
amp.put(set2[0][jj], amp.getOrDefault(set2[0][jj], 0) + 1);
} for (int jj = 0; jj < 3; jj++) {
amp.put(set3[0][jj], amp.getOrDefault(set3[0][jj], 0) + 1);
} processLeft(ans, amp); }
}
}
} private static void processLeft(HashSet<String> ans, Map<String, Integer> amp) {
String[] left = new String[4];
int idx = 0;
for (Map.Entry<String, Integer> entry : occuredTimes.entrySet()) {
String str = entry.getKey();
int val = entry.getValue(); if (!amp.containsKey(str)) {
for (int x = 1; x <= val; x++) {
left[idx++] = str;
}
continue;
} else if (val > amp.get(str)) {
for (int x = amp.get(str) + 1; x <= val; x++) {
left[idx++] = str;
}
}
}
processLeft3(ans, left);
} public static int getMin(int sum) {
if (sum <= 4) {
return 1;
} else if (sum <= 7) {
return 1;
} else if (sum <= 10) {
return 2;
}
return 3;
} /* List<String> 表示哪3个凑一起;
String[4][3] 表示3个凑成的一个划分;
List<String[4][3]> 表示凑成的划分集合
*/
public static void dfs(int[] arr, char type, int idx, int depth, String[][] collection, int minNum) {
if (depth >= minNum) {
String[][] set = new String[depth][3];
for (int i = 0; i < depth; i++) {
set[i] = new String[]{"", "", ""};
for (int j = 0; j < 3; j++) {
set[i][j] = "" + collection[i][j];
}
}
switch (type) {
case 'm':
m9Collections[depth - 1].add(set);
break;
case 's':
s9Collections[depth - 1].add(set);
break;
case 'p':
p9Collections[depth - 1].add(set);
break;
case 'c':
c7Collections[depth - 1].add(set);
break;
default:
break;
}
return;
} if (idx >= arr.length) {
return;
} //是3个的
if (arr[idx] >= 3) {
arr[idx] -= 3;
String str = "" + idx + type;
collection[depth] = new String[]{str, str, str};
dfs(arr, type, idx, depth + 1, collection, minNum);
arr[idx] += 3;
} //是连续
if (type != 'c' && arr[idx] > 0 && idx + 2 < arr.length && arr[idx + 1] > 0 && arr[idx + 2] > 0) {
arr[idx] -= 1;
arr[idx + 1] -= 1;
arr[idx + 2] -= 1; String str1 = "" + idx + type;
String str2 = "" + (idx + 1) + type;
String str3 = "" + (idx + 2) + type; collection[depth] = new String[]{str1, str2, str3};
dfs(arr, type, idx, depth + 1, collection, minNum); arr[idx] += 1;
arr[idx + 1] += 1;
arr[idx + 2] += 1; } //这个元素不获取;
dfs(arr, type, idx + 1, depth, collection, minNum); } private static void processLeft3(HashSet<String> ans, String[] left) {
Arrays.sort(left, cmp); //4个A的场景;
//获取剩下的两个AAAA
String s0 = left[0];
String s1 = left[1];
String s2 = left[2];
String s3 = left[3];
if (s0.equals(s1) && s1.equals(s2) && s2.equals(s3)) {
return;
}
//AAAC
if (s0.equals(s1) && s1.equals(s2)) {
if (occuredTimes.getOrDefault(s3, 0) < 4) {
ans.add(s3);
}
lianxu(ans, s2, s3);
return;
} if (s1.equals(s2) && s2.equals(s3)) {
if (occuredTimes.getOrDefault(s0, 0) < 4) {
ans.add(s0);
}
lianxu(ans, s0, s3);
return;
}
//AABB;
if (s0.equals(s1) && s2.equals(s3)) {
if (occuredTimes.getOrDefault(s0, 0) < 4) {
ans.add(s0);
}
if (occuredTimes.getOrDefault(s2, 0) < 4) {
ans.add(s2);
}
return;
} //AABC;ABBC,ABCC;
if (s0.equals(s1)) {
lianxu(ans, s2, s3);
return;
} if (s1.equals(s2)) {
lianxu(ans, s0, s3);
return;
} if (s2.equals(s3)) {
lianxu(ans, s0, s1);
return;
} //ABCD;
if (check(s0, s1, s2)) {
if (occuredTimes.getOrDefault(s3, 0) < 4) {
ans.add(s3);
}
return;
} if (check(s1, s2, s3)) {
if (occuredTimes.getOrDefault(s0, 0) < 4) {
ans.add(s0);
}
return;
}
return;
} /**
* str1<str2 再加个A凑成3个连续
*
* @param ans
* @param str1
* @param str2
*/
private static void lianxu(HashSet<String> ans, String str1, String str2) {
char ch = str1.charAt(1);
char ch2 = str2.charAt(1); if (ch != ch2) {
return;
}
if (ch == 'c') {
return;
}
int d1 = str1.charAt(0) - '0';
int d2 = str2.charAt(0) - '0';
d1 = Math.min(d1, d2);
d2 = Math.max(d1, d2); if (d1 + 1 == d2) {
if (d1 > 1) {
String key = "" + (d1 - 1) + ch;
if (occuredTimes.getOrDefault(key, 0) < 4) {
ans.add(key);
}
}
if (d2 < 9) {
String key = "" + (d2 + 1) + ch;
if (occuredTimes.getOrDefault(key, 0) < 4) {
ans.add(key);
}
}
} else if (d1 + 2 == d2) {
String key = "" + (d1 + 1) + ch;
if (occuredTimes.getOrDefault(key, 0) < 4) {
ans.add(key);
}
}
} /**
* 检查是否是连续的三元,或者是三个一样的对;
*
* @param i
* @param j
* @param k
* @return
*/
public static boolean check(int i, int j, int k) {
String str1 = tiles[i];
String str2 = tiles[j];
String str3 = tiles[k]; return check(str1, str2, str3);
} private static boolean check(String str1, String str2, String str3) {
if (str1.equals(str2) && str2.equals(str3)) {
//三个相同的
return true;
} if (str1.charAt(1) != str2.charAt(1) || str1.charAt(1) != str3.charAt(1) || str2.charAt(1) != str3.charAt(1)) {
return false;
}
if (str1.charAt(1) == 'c') {
return false;
} String[] words = new String[]{str1, str2, str3}; Arrays.sort(words);
int d1 = words[0].charAt(0);
int d2 = words[1].charAt(0);
int d3 = words[2].charAt(0); if (d1 + 1 == d2 && d2 + 1 == d3) {
return true;
}
return false;
} public static void initCmp() {
String[] types = new String[]{"m", "s", "p", "c"};
for (int i = 0; i < 4; i++) {
cmpMap.put(types[i], new HashMap<>());
}
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
cmpMap.get(types[i]).put(types[j], i - j);
}
}
cmp = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
if (cmpMap.get("" + o1.charAt(1)).get("" + o2.charAt(1)) != 0) {
return cmpMap.get("" + o1.charAt(1)).get("" + o2.charAt(1));
} char d1 = o1.charAt(0);
char d2 = o2.charAt(0); return d1 - d2;
}
};
} public static void main(String[] args) throws IOException {
initCmp();
// for (int testcas = 0; testcas <= 10; testcas++) {
// BufferedReader reader = new BufferedReader(new FileReader(new File("test"+testcas)));
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
// BufferedWriter writer = new BufferedWriter(new FileWriter(new File("ans" + testcas)));
String str = reader.readLine();
int t = Integer.valueOf(str);
for (int cas = 1; cas <= t; cas++) {
str = reader.readLine();
String[] words = str.split("\\s+"); Main.tiles = words;
init(words); if (set5.size() > 0) {
System.out.println("Nooten");
continue;
} TreeSet<String> ans = new TreeSet<>(cmp);
// if (set2.size() == 6) {
ans.addAll(judge2());
// } else if (only3possible()) {
ans.addAll(judge3());
// } else {
ans.addAll(judge1());
// }
if (ans.isEmpty()) {
System.out.println("Nooten");
// writer.write("Nooten");
// writer.newLine();
} else {
//排序;
output(ans,null);
}
}
reader.close();
// writer.close();
// }
} private static void output(TreeSet<String> ans, BufferedWriter writer) throws IOException {
StringBuilder sb = new StringBuilder();
sb.append(ans.size());
for (String out : ans) {
sb.append(" ").append(out);
}
System.out.println(sb.toString());
if (writer != null) {
writer.write(sb.toString());
writer.newLine();
}
} public static List<String> judge3() {
String[] dict = new String[]{"1m", "9m", "1p", "9p", "1s", "9s", "1c", "2c", "3c", "4c", "5c", "6c", "7c"};
int missedNum = 0;
String miss0 = null;
boolean has2 = false;
for (String str : dict) {
if (!occuredTimes.containsKey(str)) {
missedNum++;
miss0 = str;
} else if (occuredTimes.get(str) == 2) {
has2 = true;
}
} if (missedNum >= 2) {
return new ArrayList<>();
} if (missedNum == 1) {
if (!has2) {
return new ArrayList<>();
}
return Arrays.asList(miss0);
} return Arrays.asList(dict);
} public static List<String> judge2() {
if (set2.size() != 6) {
return new ArrayList<>();
}
return Arrays.asList(set1.iterator().next());
} public static void init(String[] tiles) { set2 = new HashSet<>();
set3 = new HashSet<>();
set1 = new HashSet<>();
occuredTimes = new HashMap<>();
set4 = new HashSet<>();
m9 = new int[10];
s9 = new int[10];
p9 = new int[10];
c7 = new int[8];
set5 = new HashSet<>(); for (String tile : tiles) {
occuredTimes.put(tile, occuredTimes.getOrDefault(tile, 0) + 1);
}
//
sum = new int[4];
for (Map.Entry<String, Integer> entry : occuredTimes.entrySet()) {
String key = entry.getKey();
Integer value = entry.getValue(); if (value == 1) {
set1.add(key);
} else if (value == 2) {
set2.add(key);
} else if (value == 3) {
set3.add(key);
} else if (value == 4) {
set4.add(key);
} else {
set5.add(key);
}
//
int digit = key.charAt(0) - '0';
char ch = key.charAt(1); switch (ch) {
case 'm':
sum[0] += value;
m9[digit] += value;
break;
case 's':
sum[1] += value;
s9[digit] += value;
break;
case 'p':
sum[2] += value;
p9[digit] += value;
break;
case 'c':
sum[3] += value;
c7[digit] += value;
break;
default:
break;
}
} m9Collections = new ArrayList[3];
s9Collections = new ArrayList[3];
p9Collections = new ArrayList[3];
c7Collections = new ArrayList[3]; Arrays.setAll(m9Collections, e -> new ArrayList<>());
Arrays.setAll(s9Collections, e -> new ArrayList<>());
Arrays.setAll(p9Collections, e -> new ArrayList<>());
Arrays.setAll(c7Collections, e -> new ArrayList<>()); }
}

 

【Mahjong hdu 枚举】搜索枚举的更多相关文章

  1. hdu4431 Mahjong 枚举搜索。。

    japanese麻将什么玩意..都没有豪华七对... 没什么难的 就是枚举搜索了 分三种类型的胡牌 f1是七对 f2是十三幺 f3是普通的胡牌 就先找一对 再找三个三个的 就是一直超时..在峰峰的指导 ...

  2. hdu 3118(二进制枚举)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3118 思路:题目要求是去掉最少的边使得图中不存在路径长度为奇数的环,这个问题等价于在图中去掉若干条边, ...

  3. hdu 5636 搜索 BestCoder Round #74 (div.2)

    Shortest Path  Accepts: 40  Submissions: 610  Time Limit: 4000/2000 MS (Java/Others)  Memory Limit: ...

  4. hdu 5887 搜索+剪枝

    Herbs Gathering Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

  5. 深度分析Java的枚举类型—-枚举的线程安全性及序列化问题

    原文:深度分析Java的枚举类型--枚举的线程安全性及序列化问题 枚举是如何保证线程安全的 要想看源码,首先得有一个类吧,那么枚举类型到底是什么类呢?是enum吗?答案很明显不是,enum就和clas ...

  6. Square HDU 1518 搜索

    Square HDU 1518 搜索 题意 原题链接 给你一定若干个木棒,让你使用它们组成一个四边形,要求这些木棒必须全部使用. 解题思路 木棒有多种组合方式,使用搜索来进行寻找,这里需要进行优化,不 ...

  7. HDU 4900 NO ACM NO LIFE(概率+枚举+搜索)(2014 Multi-University Training Contest 4)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4900 Problem Description There is an old country and ...

  8. HDU 4431 Mahjong (DFS,暴力枚举,剪枝)

    题意:给定 13 张麻将牌,问你是不是“听”牌,如果是输出“听”哪张. 析:这个题,很明显的暴力,就是在原来的基础上再放上一张牌,看看是不是能胡,想法很简单,也比较好实现,结果就是TLE,一直TLE, ...

  9. hdu 2489(枚举 + 最小生成树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2489 思路:由于N, M的范围比较少,直接枚举所有的可能情况,然后求MST判断即可. #include ...

  10. 枚举+搜索 hdu-4431-Mahjong

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4431 题目大意: 给一副牌,求出所有能糊的牌. 解题思路: 枚举每一张牌,看能不能糊. 因为一共只有 ...

随机推荐

  1. Java - CodeForces - 469C

    题目: 现在有一个容器,里面有n个物品,编号为1-n,现在小q可以进行一些操作,每次取出任意两个数,可以把这两个数的编号相加,相减,相乘,再把结果放回容器.问最后小q能否在n-1次操作后使得容器里的唯 ...

  2. Spring boot 的定时任务。

    @Scheduled(fixedRate=2000):上一次开始执行时间点后2秒再次执行: @Scheduled(fixedDelay=2000):上一次执行完毕时间点后2秒再次执行: @Schedu ...

  3. 【简写MyBatis】01-简单映射器

    前言 新开一个坑,为了学习一下MyBatis的源码,写代码是次要的,主要为了吸收一下其中的思想和手法. 目的 关联对象接口和映射类的问题,把 DAO 接口使用代理类,包装映射操作. 知识点 动态代理 ...

  4. C#开源免费的Windows右键菜单管理工具

    前言 今天分享一个C#开源.免费.纯粹的Windows右键菜单管理工具:ContextMenuManager. 工具主要功能 程序支持国际化多语言显示. 启用或禁用文件.文件夹.新建.发送到.打开方式 ...

  5. 使用OpenWrt实现IPv6 DDNS

    OpenWrt 增加 crontab 任务 在/root/crontab/ 目录下, 创建脚本 ddns.sh #!/bin/sh # 远程php脚本的URL地址 SERVICE_URL=http:/ ...

  6. SpringBoot相关注解使用

    @MapperScan注解和@Mapper @Mapper常用在相应的 *Mapper类上,但是每个类都使用相对麻烦,所以后来用@MapperScan替代 ,@MapperScan注解使用在启动类上. ...

  7. SpringBoot+Shiro+LayUI权限管理系统项目-7.实现用户管理

    1.说明 只讲解关键部分,详细看源码,文章下方捐赠或QQ联系捐赠获取. 2.功能展示 包括用户增删改查和分配角色. 3.业务模型 @Data @EqualsAndHashCode(callSuper ...

  8. Eclipse搭建Struts2项目

    最近在系统性的学习maven,碰到搭建struts2环境,特此记录一下. 1.创建maven工程 2.添加依赖 pom.xml文件内容如下 <project xmlns="http:/ ...

  9. 使用SecScanC2构建P2P去中心化网络实现反溯源

    个人博客: xzajyjs.cn 前言 这款工具是为了帮助安全研究人员在渗透测试过程中防止扫描被封禁.保护自己免溯源的一种新思路.其利用到了区块链中的p2p点对点去中心化技术构建以来构建代理池. 工具 ...

  10. geacon_pro配合catcs4.5上线Mac、Linux

    最新最全文章见我个人博客: xzajyjs.cn 一些链接 Try师傅的catcs4.5项目: https://github.com/TryGOTry/CobaltStrike_Cat_4.5,最新版 ...