#####枚举
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. Excel分类后数字类型的内容值后面变为0

    背景 在工作中经常遇到从日志或者其他地方拷贝过来的文本,里面使用其他分隔符进行分割.然而,使用Excel的分列功能进行分列后,发现数字类型的数值后面变为0. 有时候我们就是需要原先的数值,该怎么办呢? ...

  2. 通过解析库探究函数式抽象代价 ( ini 解析示例补充)

    上一篇 用 HexColor 作为示例,可能过于简单 这里再补充一个 ini 解析的示例 由于实在写不动用其他库解析 ini 了, 春节都要过完了,累了,写不动了, 所以随意找了一份解析ini的库, ...

  3. 在nginx 服务器部署vue项目

    以人人快速开发的开源项目:renren-fast-vue 为例 注:这里开始认为各位都会使用nginx 打包vue项目 npm run build 测试打包的项目是否可以运行 serve dist 可 ...

  4. 从 KeyStore 中获取 PublicKey 和 PrivateKey

    KeyStore(译:密钥存储库) 代表用于加密密钥和证书的存储设施. KeyStore 管理不同类型的 entry(译:条目).每种类型的 entry 都实现了 KeyStore.Entry 接口. ...

  5. Java设计模式-解释器模式Interpreter

    介绍 在编译原理中,一个算术表达式通过词法分析器形成词法单元,而后这些词法单元再通过语法分析器构建语法 分析树,最终形成一颗抽象的语法分析树.这里的词法分析器和语法分析器都可以看做是解释器 解释器模式 ...

  6. linux中cron表达式指南

    Cron是什么? 简单来讲,cron是基于Unix的系统上的一个实用程序.它使用户能够安排任务在指定的[日期/时间]定期运行.它自然是一个伟大的工具,可以自动运行大量流程,否则需要人工干预. Cron ...

  7. Java并发编程实例--14.在一个同步类中安排独立属性

    当你使用synchronized关键字去保护一个代码块时,你必须传入一个对象的引用. 正常来讲,你讲使用this关键字去引用执行这个方法的对象,但是你可以使用其他对象的引用. 通常的,这些对象将会是专 ...

  8. EXPLAIN命令

    EXPLAIN命令   除了以SELECT开头的查询语句,其余的DELETE.INSERT.REPLACE以及UPDATE语句前边都可以加上EXPLAIN这个词儿,用来查看这些语句的执行计划   Ty ...

  9. CentOS 8安装RabbitMQ

    第一步:安装yum仓库 导入签名KEY: ## primary RabbitMQ signing key ## 这一步如果因为网络问题下载不成功,可以先将签名文件下载下来,本地导入 rpm --imp ...

  10. day07---系统命令

    课程知识概述--系统命令 seq cat less more head tail grep tr alias 复习 1.echo -e 激活特殊的意义 \n 表示回车 \t tab键 [root@ol ...