题解 | #数组分组#动态规划#,注意边界

数组分组

https://www.nowcoder.com/practice/9af744a3517440508dbeb297020aca86

import java.util.*;
import java.lang.*;
import java.util.stream.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        int array_raw_length = in.nextInt();
        List<Integer> list_raw = new ArrayList<Integer>();
        boolean result = false;
        while (in.hasNextInt()) {
            list_raw.add(in.nextInt());
        }
        List<Integer> listfor5 = new ArrayList<Integer>();
        List<Integer> listfor3 = new ArrayList<Integer>();
        List<Integer> listsuplus = new ArrayList<Integer>();
        list_raw.forEach(a-> {
            if (a % 5 == 0) {
                listfor5.add(a);
            } else if (a % 3 == 0) {
                listfor3.add(a);
            } else {
                listsuplus.add(a);
            }
        });
        int sum = list_raw.stream().reduce((a, b)-> {return a + b;}).get();
        if (Math.abs(sum) % 2 > 0) {
            result = false;
        } else if (list_raw.size() == 0) {
            result = true;
        } else {
            int target = sum / 2 - (listfor5.size() > 0 ? listfor5.stream().reduce((a, b)-> {return a + b;}).get()
                                    : 0);
            int left_boundary = Math.abs(listsuplus.stream().filter(
                                             a->a < 0).count() > 0 ? listsuplus.stream().filter(a->a < 0).reduce((a, b)-> {return a + b;}).get()
                                         : 0);
            int right_boundary = listsuplus.stream().filter(a->a > 0).count() > 0 ?
                                 listsuplus.stream().filter(a->a > 0).reduce((a, b)-> {return a + b;}).get(): 0;
            int length = left_boundary + right_boundary + 1;
            boolean[][] dp = new boolean[listsuplus.size()][length];
            if (length == 1) {
                if (target == 0) {
                    result = true; 
                }
            } else if(target<-left_boundary||target>right_boundary){
                    result = false;
            }else{
                //初始化
                for (int j = 0; j < length - 1; j++) {
                    if (listsuplus.get(0) == j - left_boundary) {
                        dp[0][j] = true;
                    } else {
                        dp[0][j] = false;
                    }
                }
                //j=0是有意义的,dp[i-1][0] = dp[i][j]&&j==vi。解释一下,当前元素值恰好是目标的时候,当前元素刚好装进目标,肯定是true,那么就相当于之前所有元素的集合什么不用选择,
                //这两个概念是等价的,是反推出来的。
                for(int i=0;i<listsuplus.size();i++){
                    dp[i][left_boundary] = true;
                }
                //利用动态规划继续求dp
                for (int i = 1; i < listsuplus.size(); i++) {
                    for (int j = 0; j < length; j++) {
                        if ((j - left_boundary - listsuplus.get(i)) >= -left_boundary &&
                                (j - left_boundary - listsuplus.get(i)) <= right_boundary) {
                            dp[i][j] = dp[i - 1][j] || dp[i - 1][j - listsuplus.get(i)];
                        } else {
                            dp[i][j] = dp[i - 1][j];
                        }
                    }
                }
                for (int i = 0; i < listsuplus.size(); i++) {
                    if (dp[i][target + left_boundary] == true) {
                        result = true;
                        break;
                    }
                }
            }


        }
        System.out.println(result);


    }
}

全部评论

相关推荐

不愿透露姓名的神秘牛友
07-04 11:46
酷酷我灵儿帅:这去不去和线不线下面说实话没啥关系
点赞 评论 收藏
分享
07-13 21:50
门头沟学院 Java
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务