【Mahjong hdu 枚举】搜索枚举

#####枚举
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<>());


    }
}

 

 
posted @ 2022-05-04 22:30  fishcanfly  阅读(43)  评论(0)    收藏  举报
//雪花飘落效果