#####枚举
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. CTAS建表时报错ORA-65114

    环境: Oracle 19.16 多租户架构 1.问题现象: SQL> create table T1 as select * from v$active_session_history * E ...

  2. 案例:OGG目标端进程ABENDED处理

    源端环境:RHEL 6.5 + Oracle 11.2.0.4 RAC + OGG 19.1.0.0.4 目标端环境:RHEL 7.6 + Oracle 19.3 + OGG 19.1.0.0.4 故 ...

  3. 《ASP.NET Core 与 RESTful API 开发实战》-- (第9章)-- 读书笔记(上)

    第 9 章 测试和文档 9.1 测试 测试是软件生命周期中的一个非常重要的阶段,对于保证软件的可靠性具有极其重要的意义 常见的测试方法有很多,根据不同的维度,可以把测试方法分为不同的类别 从观察结构的 ...

  4. 《ASP.NET Core 与 RESTful API 开发实战》-- (第8章)-- 读书笔记(上)

    第 8 章 认证和安全 8.1 认证 认证(Authentication)是指验证用户身份的过程,授权(Authorization)是验证一个已经通过认证的用户是否有权限做某些事的过程 常见的 HTT ...

  5. react 快速接入 sentry,性能监控与错误上报踩坑日记

    壹 ❀ 引 本文是我入职第一个月所写,在主导基建组的这段时间也难免会与错误监控和性能监控打交道,因为公司主要考虑接入sentry,所以对于接入sentry的基建任务也提了一些需求,主要分为: 支持查看 ...

  6. react实战 系列

    react实战 系列(未完结,持续更新中...) 前言 学习 react 的方法,比较常规的是跟着官方文档边看边做,可是 react 的官网教程有点难(至少比 vue 的难),亦或买几本讲基础的或实战 ...

  7. java 从零开始手写 RPC (06) reflect 反射实现通用调用之客户端

    通用调用 java 从零开始手写 RPC (01) 基于 socket 实现 java 从零开始手写 RPC (02)-netty4 实现客户端和服务端 java 从零开始手写 RPC (03) 如何 ...

  8. 如何避免FOUC

    如何避免FOUC FOUC即无样式内容闪烁也可以称为文档样式短暂失效,主要就是指HTML已加载而样式表并未加载,此后样式表再加载而产生的闪烁现象. 样式表前置 根据浏览器渲染的顺序,将CSS在< ...

  9. java常用包下载地址(非maven)

    httpclient与httpcore: http://hc.apache.org/downloads.cgi jdbc: https://dev.mysql.com/downloads/connec ...

  10. python第二章pta习题总结

    chapter2 一.选择填空判断部分 1. C语言中,变量变的是内存空间中的值,不变的是地址: Python中,变量变的是地址,不变的是内存空间中的值. 2. 3.bool('False') 的返回 ...