通过过万岁!!!
- 题目,给定n根木棍,然后分成m组,然后找m组木棍之和中的最大值和最小值的差值,使得差值最小。
- 超时思路:第一思路就是暴力了,也就是递归的将第j个木棍分给第i组。也就是说,然后定义一个lens的数组,记录每组的长度,最后求解lens的最大值和最小值。然后求差值,并与原插值进行比较。但是这种思路超时了,后来我还想,我有一层for基本都有干事情,而递归本身其实就是一层for,所以可以进行优化。其实这整体的思路就是dfs,也就是深度优先遍历,只不过我不是很熟练,所以走了一点弯路。
- 正确思路:我们要将idx根木棍给第i组,但是这个idx是由递归控制的,而不是for控制。
- 题目链接:http://lx.lanqiao.cn/problem.page?gpid=T2982
- 技巧:dfs,深度优先
超时java代码
import java.util.Scanner;
/**
* @创建人 xcs
* @创建日期 2022/3/24
* @创建时间 9:31
* 题目链接:http://lx.lanqiao.cn/problem.page?gpid=T2982
*/
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int m = scanner.nextInt();
// 每根杆子的长度
int[] nums = new int[n];
// 粘贴之后的长度
int[] lens = new int[m];
int[] vis = new int[n];
for (int i = 0; i < n; i++) {
nums[i] = scanner.nextInt();
}
int sub = getSub(nums, lens, vis, 0, Integer.MAX_VALUE);
System.out.println(sub);
}
private static int getSub(int[] nums, int[] lens, int[] vis, int flag, int sub) {
if (flag == nums.length) {
// 已经都分配完了,开始找最大值和最小值
int max = -1, min = Integer.MAX_VALUE;
for (int i = 0; i < lens.length; i++) {
// 如果存在lens==0,则表示这一组中没有分配木棍,这时候是不符合要求的,直接return
if (lens[i]==0){
return sub;
}
max = Math.max(max, lens[i]);
min = Math.min(min, lens[i]);
}
sub = Math.min(sub, max - min);
return sub;
}
// m
for (int i = 0; i < lens.length; i++) {
// n
for (int j = 0; j < nums.length; j++) {
// 用过了
if (vis[j] != 0) {
continue;
}
// 没用过,给i+1组用
vis[j] = i + 1;
lens[i] += nums[j];
flag++;
sub = getSub(nums, lens, vis, flag, sub);
flag--;
lens[i] -= nums[j];
vis[j] = 0;
}
}
return sub;
}
}
正确的java代码
import java.util.Scanner;
/**
* @创建人 xcs
* @创建日期 2022/3/24
* @创建时间 9:31
* 题目链接:http://lx.lanqiao.cn/problem.page?gpid=T2982
*/
public class ALGO997 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int m = scanner.nextInt();
// 每根杆子的长度
int[] nums = new int[n];
// 粘贴之后的长度
int[] lens = new int[m];
int[] vis = new int[n];
for (int i = 0; i < n; i++) {
nums[i] = scanner.nextInt();
}
int sub = getSub(nums, lens, vis, 0, 0, Integer.MAX_VALUE);
System.out.println(sub);
}
private static int getSub(int[] nums, int[] lens, int[] vis, int idx, int flag, int sub) {
if (flag == nums.length) {
// 已经都分配完了,开始找最大值和最小值
int max = -1, min = Integer.MAX_VALUE;
for (int i = 0; i < lens.length; i++) {
// 如果存在lens==0,则表示这一组中没有分配木棍,这时候是不符合要求的,直接return
if (lens[i] == 0) {
return sub;
}
max = Math.max(max, lens[i]);
min = Math.min(min, lens[i]);
}
sub = Math.min(sub, max - min);
return sub;
}
// m
for (int i = 0; i < lens.length; i++) {
// idx没有用过,让i用上idx
if (vis[idx] == 0) {
vis[idx] = 1;
lens[i] += nums[idx];
flag++;
sub = getSub(nums, lens, vis, idx + 1, flag, sub);
flag--;
lens[i] -= nums[idx];
vis[idx] = 0;
}
}
return sub;
}
}
- 总结:虽然图这一块不是很熟悉,但是也做了bfs和dfs了,大概有所了解了。需要注意的是递归本身就是一层for,可以省略一层for。