题解 | #数组分组#动态规划#,注意边界
数组分组
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); } }