題目:
輸入描述:每組的第一行包含一個整數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; } }
