查找和為24的子集合


題目:

輸入描述:每組的第一行包含一個整數n(1<=n<=23),第二行包含n個整數(1<= 整數 <= 23)

輸出描述:

對每個測試實例,要求輸出能組成24點的所有子集合的數量(子集合相互不同)。如果不存在,則輸出0。每個測試實例的輸出占用一行。

示例:

輸入:

5

1 1 2 22 23

輸出:

3

樣例解析:方法有      1+23,   2+22 ,1+1+22三種

思路:如果用2進制法來賦值判斷的話,肯定會超時,需要不斷剪枝。提供另一種思路:類似爬樓梯

首先回顧爬樓梯:有100個樓梯,每次爬1或者2個台階,問總共有幾種方法。

可以用DP的思維,可以知道,如果想知道100個樓梯的爬法,可以分為最后一步為1步的,和最后一步為2步的,

那么如果是最后一步為1步的,那就是(爬99個樓梯)的方法數,同理最后一步為2步的,就是(爬98個樓梯)的方法數

所以可以得到DP方程為DP[i+2]=DP[i+1]+DP[i]

,我們再來回顧一下這個題目:當你有n個數的時候

思路:給了我們n個數,加入我們已經[n-1]個數的各種數目的組合情況,那可以明白,再在集合中加入第n個數字a[n-1]的時候,想知道和為24的子集有多少個,那子集可以分為包含第n個數與不包含第n個數,

那包含第n個數其實就是只有[n-1]個數時候,和為24-a[n-1]的子集的個數,

不包含第n個數其實就是只有[n-1]個數時候,和為24的子集的個數

兩種集合相加,再對相同子集去重即可。

同樣,我們既然能維護和為24的個數,那和為1,2,3,4,5.。。。24的子集,我們都可以維護

題解:申明24個arrayList<String> 用於存放為1-24的子集和的排序后轉為string的列表,然后通過一個數一個數加進來,維護這個集合

代碼:

import java.util.*;

public class Main {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int len = in.nextInt();
        int[] ints = new int[len];
        for (int i = 0; i < len; i++) { //輸入n個數,保存起來
            ints[i] = in.nextInt();
        }
        Node[] nodes = new Node[25];
        for (int i = 0; i <= 24; i++) {//申請24個ArrayList
            Node node = new Node();
            node.setList(new ArrayList<String>());
            nodes[i] = node;
        }
        for (int i = 0; i < len; i++) { //從第一個數開始,以此一個個維護
            int num = ints[i];
            for (int j = 24 - num; j > 0; j--) { //從后往前維護,避免重復進入,即將和為j的子集合中,加入和為[j-ints[i]]的個數,並且一個個加的時候,需要去重
                List<String> fromList = nodes[j].getList();
                List<String> toList = nodes[j + num].getList();
                for (String s : fromList) {
                    List<Integer> list = StringToList(s);
                    list.add(num);
                    Collections.sort(list);
                    String string = ListToString(list);
                    if(!toList.contains(string)) {
                        toList.add(string);
                    }
                }
                nodes[j + num].setList(toList);
            }
            List<String> list = nodes[num].getList();
            Integer integer = num;
            list.add(integer.toString()); //此步驟其實需要判斷num是否在和為num的子集合中,但是不判斷也可以,因為其實判斷了后,在進入和為24的集合中的時候,會被過濾掉
            nodes[num].setList(list);
        }
        System.out.println(nodes[24].getList().size());
    }

    private static List<Integer> StringToList(String s) {
        List<Integer> strings = new ArrayList<>();
        if (s == null || s.length() == 0) {
            return strings;
        }
        String[] split = s.split(",");
        for (String str : split) {
            strings.add(new Integer(str));
        }
        return strings;
    }

    private static String ListToString(List<Integer> integers) {
        if (integers.size() == 0) {
            return "";
        }
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(integers.get(0));
        for (int i = 1; i < integers.size(); i++) {
            stringBuilder.append(",").append(integers.get(i));
        }
        return stringBuilder.toString();
    }
}


class Node {
    private List<String> list;

    public List<String> getList() {
        return list;
    }

    public void setList(List<String> list) {
        this.list = list;
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM