输入描述:每组的第一行包含一个整数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; } }
原文:https://www.cnblogs.com/dadddd/p/13669965.html