题目描述
小蓝正在一个瓜摊上买瓜。瓜摊上共有 n 个瓜,每个瓜的重量为 Ai 。
小蓝刀功了得,他可以把任何瓜劈成完全等重的两份,不过每个瓜只能劈一刀。
小蓝希望买到的瓜的重量的和恰好为 m 。
请问小蓝至少要劈多少个瓜才能买到重量恰好为 m 的瓜。如果无论怎样小蓝都无法得到总重恰好为 m 的瓜,请输出 −1 。
输入格式
输入的第一行包含两个整数 n, m,用一个空格分隔,分别表示瓜的个数和小蓝想买到的瓜的总重量。
第二行包含 n 个整数 Ai,相邻整数之间使用一个空格分隔,分别表示每个瓜的重量。
输出格式
输出一行包含一个整数表示答案。
样例输入
复制
3 10 1 3 13
样例输出
复制
2
import java.util.Scanner;
public class Main {
static int n, m, min = 100;
static long suf[],arr[];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();//瓜的总数
m = sc.nextInt();//想买的重量
arr = new long[n];
for (int i = 0; i < n; i++) {
arr[i] = sc.nextLong();//每个瓜的重量
}
suf = new long[n + 1];// 后缀和
for (int i = n - 1; i >= 0; i--) {
suf[i] = suf[i + 1] + arr[i];
}
dfs(0, 0, 0);
if (min == 100)
System.out.println(-1);
else
System.out.println(min);
}
static void dfs(int i, double sum, int c) {//第i个瓜,当前已经买的重量总和,已经劈瓜的次数
//剪枝就是当前方案已经不可能在符合要求,提前中断当前方案
if (suf[i] + sum < m) return;// 剪枝,如果当前重量sum加上剩余所有值都小于m,就算全买也不够重量
if (sum > m) return; // 剪枝,如果当前重量sum已经大于m,即可提前结束
if (c >= min) return; // 剪枝,劈瓜的次数大于等于最小值,即使能满足要求m也没有意义,因为它不是最小的
if (sum == m) {
min = c;
}
for (int j = i; j < n; j++) {
sum += arr[j]; //整个西瓜拿走
dfs(j + 1, sum, c);
sum -= arr[j] / 2.0; //拿走一半
dfs(j + 1, sum, c + 1);
sum -= arr[j] / 2.0; //不拿走,另一半也减去,因为当前瓜没有做任何操作,所以不需要进入dfs,而是直接跳转到下一个瓜
}
}
}