import java.util.Scanner;
import java.util.Stack;

public class Main {
    public static void main(String[] args) {

        //这道题的思想
        System.out.println(fun());

    }
    public static boolean fun() {
        Scanner in = new Scanner(System.in);
        int m = in.nextInt();
        int a = 0;
        int b = 0;
        int c = 0;
        //事先将这两个分组

        int[] n = new int[m];
        Stack<Integer> stack = new Stack<>();
        int sum_max = 0, offset = 0; //计算前后的偏移量
        for (int i = 0; i < m; i++) {
            n[i] = in.nextInt();
            if (n[i] % 5 == 0) {
                a += n[i];
            } else if ( n[i] % 3 == 0) {
                b += n[i];
            } else {
                stack.push(n[i]);
                sum_max += Math.abs(n[i]);
                //用于移位的
                offset += n[i] >= 0 ? 0 : Math.abs(n[i]);
                c += n[i];
            }
        }

        //转为为背包问题   先将两个集合分类

        //leetcode416 耐心复习

      
        int s = b + c - a;

      
        if (s % 2 != 0) return false;
        if (stack.size() == 0) return s == 0;
           if (stack.size()==1) return s==stack.peek()||s==-stack.peek(); //1
        int tar = stack.size();

        s /= 2;
        //两个都要加个一作为缓冲
        boolean[][] dp = new boolean[tar + 1][sum_max + 1];

        int[] num = new int[tar];
        for (int i = tar - 1; i >= 0 ; i--) {
            num[i] = stack.pop();    
        }
        //将dp数组处理的位置换个地方
        //原来的初始化是有问题的  dp[0][0】 那个部分问题
        dp[0][offset] = true;
        for (int i = 1; i <= tar ; i++) {
            int x = num[i - 1];
            for (int j = sum_max; j >= 0; j--) { //有负的计算的时候看右上方
                dp[i][j] = dp[i - 1][j];
                if (j - x > sum_max || j - x < 0) continue;
                dp[i][j] = dp[i - 1][j - x] || dp[i][j];
            }
        }
        if(s + offset<0||s+offset>sum_max) return false; //2
        return dp[tar][s + offset];
    }
}



将题目转化为01背包做题,由于与416的区别在于此时可能为负数,需要便宜
416 的dp【i,0 】=true这一核心点,之后的根据这个同时对dp【0,offset】 之前的dp【i,0 】=true那个情况的转变,代码随想录的初始化方式有问题,建议看力扣官网。
C语言数组越界不报错,这里越界的话直接就是无解

还是去看递归的实现