import java.util.*; /** * NC385 划分等和序列 * @author d3y1 */ public class Solution { private boolean[] visited; private int avg; /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param nums int整型ArrayList * @param k int整型 * @return bool布尔型 */ public boolean candivide (ArrayList<Integer> nums, int k) { return solution1(nums, k); // return solution2(nums, k); } /** * 动态规划: 01背包 * * dp[j]表示背包大小为j时能够组成的最大的和(数组中的元素和)[数组中每个元素仅用一次] * * dp[j] = Math.max(dp[j], dp[j-num] + num) * * @param nums * @param k * @return */ private boolean solution1(ArrayList<Integer> nums, int k){ int n = nums.size(); int sum = 0; for(int i=0; i<n; i++){ sum += nums.get(i); } if(sum%k != 0){ return false; } avg = sum/k; int[] dp = new int[sum+1]; int num; for(int i=0; i<n; i++){ num = nums.get(i); if(num > avg){ return false; } // 数组中每个元素仅用一次 -> 降序 for(int j=sum; j>=num; j--){ dp[j] = Math.max(dp[j], dp[j-num] + num); } } // avg的倍数 均要判断 for(int i=1; i<=k; i++){ // 恰好装满 -> 恰好组成下一个元素和avg if(dp[avg*i] != avg*i){ return false; } } return true; } /** * dfs: 遍历解空间 * @param nums * @param k * @return */ private boolean solution2(ArrayList<Integer> nums, int k){ int n = nums.size(); visited = new boolean[n]; int sum = 0; for(int i=0; i<n; i++){ sum += nums.get(i); } if(sum%k != 0){ return false; } int avg = sum/k; return dfs(nums, k, avg); } /** * dfs: 递归 * @param nums * @param k * @param target * @return */ private boolean dfs(ArrayList<Integer> nums, int k, int target){ if(k == 0){ return true; } if(target == 0){ if(dfs(nums, k-1, avg)){ return true; } }else if(target < 0){ return false; }else{ for(int i=0; i<nums.size(); i++){ if(!visited[i]){ visited[i] = true; if(dfs(nums, k, target-nums.get(i))){ return true; } visited[i] = false; } } } return false; } }