首页 > 其他 > 详细

查找和为24的子集合

时间:2020-09-14 23:31:53      阅读:260      评论:0      收藏:0      [点我收藏+]

题目:

输入描述:每组的第一行包含一个整数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;
    }
}

 

查找和为24的子集合

原文:https://www.cnblogs.com/dadddd/p/13669965.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!