题目描述
Perket 是一种流行的美食。为了做好 Perket,厨师必须谨慎选择食材,以在保持传统风味的同时尽可能获得最全面的味道。你有 n 种可支配的配料。对于每一种配料,我们知道它们各自的酸度 s 和苦度 b。当我们添加配料时,总的酸度为每一种配料的酸度总乘积;总的苦度为每一种配料的苦度的总和。
众所周知,美食应该做到口感适中,所以我们希望选取配料,以使得酸度和苦度的绝对差最小。
另外,我们必须添加至少一种配料,因为没有任何食物以水为配料的。
输入格式
第一行一个整数 n,表示可供选用的食材种类数。
接下来 n 行,每行 2 个整数 si 和 bi,表示第 i 种食材的酸度和苦度。
输出格式
一行一个整数,表示可能的总酸度和总苦度的最小绝对差。
思路:递归深搜,每一轮都有两个分支,决定是否选取下个元素。由于我们最终需要返回最小值,用一个长度为1的数组(数组是地址传参)去接结果。
深搜算法:
// 深搜算法
public static void dfs(int i,int n,int bi,int ac,int[] ans){
// i 用于记录层数,n 层为止 bi 代表苦度 ac 代表酸度 ans 接结果
if(i >= n){
if(bi == 0){
// 苦度初始化为0,酸度初始化为1
// 未选取任意一种食材
return;
}
ans[0] = Math.min(ans[0],Math.abs(ac - bi));
return;
}
dfs(i + 1,n,bi,ac,ans); // 不选
dfs(i + 1,n,bi + arr[i][1],ac*arr[i][0],ans); // 选
}
主程序:
public class P2036 {
public static int[][] arr;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
arr = new int[n][2];
int[] ans = new int[1]; // 记录答案
ans[0] = Integer.MAX_VALUE;
for (int i = 0; i < n; i++) {
arr[i][0] = sc.nextInt();
arr[i][1] = sc.nextInt();
}
dfs(0,n,0,1,ans);
System.out.println(ans[0]);
}
}