娜神平衡
由于题目中给出说,数据量很小,预计可以使用全排列进行。那么枚举数组的子集应该不会超时。
将一个数组划分成两部分集合,如果集合满足要求,那么对数组的差值进行判断,如果小于最小值,就更新答案。
由于不会判断是否满足生成的可行性,所以首先将集合枚举,不进行满足要求判断,可以看到,能够得60分。
那么下一步就是要判断生成的集合是否可以满足生成条件。
60分代码
package lanqiao.imporve;
import java.lang.reflect.Array;
import java.util.*;
/**
* @author: Zekun Fu
* @date: 2022/10/12 10:13
* @Description: 娜神平衡
*/
public class NaShenBalance {
public static boolean valid() {
// 如果是一个组数,那么排列可以生成
// 对于每一个排列
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int r = sc.nextInt();
int[] a = new int[n];
int sum = 0;
for (int i = 0; i < n; i++) {
a[i] = sc.nextInt();
sum += a[i];
}
int minv = Integer.MAX_VALUE;
List<Integer>ans1 = new ArrayList<>();
List<Integer>ans2 = new ArrayList<>();
for (int i = 0; i < 1 << n; i++) {
int flag = 2;
List<Integer>a1 = new ArrayList<>();
List<Integer>a2 = new ArrayList<>();
int tmp = 0;
for (int j = 0; j < n; j++) {
if ((i >> j & 1) != 0) {
tmp += a[j];
if (j == 0) flag = 1;
a1.add(a[j]);
} else a2.add(a[j]);
}
// if (!valid(a1, a2)) continue;
int s = sum - tmp;
int sub = Math.abs(s - tmp);
if (minv > sub) {
minv = sub;
ans1.clear();
ans2.clear();
if (flag == 1) {
ans1.addAll(a1);
ans2.addAll(a2);
} else {
ans1.addAll(a2);
ans2.addAll(a1);
}
}
minv = Math.min(minv, Math.abs(tmp - s));
}
ans1.sort(Integer::compareTo);
ans2.sort(Integer::compareTo);
// System.out.println(minv);
for (int i = 0; i < ans1.size(); i++) {
System.out.print(ans1.get(i));
if (i != ans1.size() - 1) System.out.print(" ");
else System.out.println();
}
for (int i = 0; i < ans2.size(); i++) {
System.out.print(ans2.get(i));
if (i != ans2.size() - 1) System.out.print(" ");
else System.out.println();
}
}
}
满分代码
package lanqiao.imporve;
import java.lang.reflect.Array;
import java.util.*;
/**
* @author: Zekun Fu
* @date: 2022/10/12 10:13
* @Description: 娜神平衡
*/
public class NaShenBalance {
public static boolean valid(Integer []val1, Integer [] val2, int r) { // 可以使用状态压缩
int x = 0, y = 0, sum1 = 0, sum2 = 0, flag = 1;
if (val1.length == 0 || val2.length == 0) {
for (Integer t : val1) sum1 += t;
for (Integer t: val2) sum2 += t;
return Math.abs(sum1 - sum2) <= r;
}
sum1 = val1[x++];
while (Math.abs(sum1 - sum2) <= r && flag == 1) {
flag = 0;
if (x < val1.length && Math.abs(sum1 + val1[x] - sum2) <= r) {
flag = 1;
sum1 += val1[x];
x++;
}
if (y < val2.length && Math.abs(sum1 - val2[y] - sum2) <= r) {
flag = 1;
sum2 += val2[y];
y++;
}
}
if (x == val1.length && y == val2.length) {
return true;
}
return false;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int r = sc.nextInt();
int[] a = new int[n];
int sum = 0;
for (int i = 0; i < n; i++) {
a[i] = sc.nextInt();
sum += a[i];
}
int first = a[0];
Arrays.sort(a);
int minv = Integer.MAX_VALUE;
List<Integer>ans1 = new ArrayList<>();
List<Integer>ans2 = new ArrayList<>();
for (int i = 1; i < (1 << n) - 1; i++) {
List<Integer>a1 = new ArrayList<>();
List<Integer>a2 = new ArrayList<>();
int tmp = 0;
for (int j = 0; j < n; j++) {
if ((i >> j & 1) != 0) {
tmp += a[j];
a1.add(a[j]);
} else a2.add(a[j]);
}
if (!valid(a1.toArray(new Integer[a1.size()]), a2.toArray(new Integer[a2.size()]), r)) continue;
int flag = 0;
for (int j = 0; j < a1.size(); j++) {
if (a1.get(j) == first) {
flag = 1;
}
}
if (flag == 1) {
ans1.addAll(a1);
ans2.addAll(a2);
}else {
ans1.addAll(a2);
ans2.addAll(a1);
}
break;
}
for (int i = 0; i < ans1.size(); i++) {
System.out.print(ans1.get(i));
if (i != ans1.size() - 1) System.out.print(" ");
else System.out.println();
}
for (int i = 0; i < ans2.size(); i++) {
System.out.print(ans2.get(i));
if (i != ans2.size() - 1) System.out.print(" ");
else System.out.println();
}
}
}
相关思考
- 正确性存在疑问。由于这个valid是抄袭的,所以不知道代码的正确性。个人感觉这种缺少了证明,看代码是贪心的思想。就是从小到大放在两个数组中,没有考虑别的情况,不知道是否正确。
- 是否可以使用别的方法做下?dfs + 回溯一定是可以的,因为这可以看作是一个选择问题,每一个数字有两个选择。还可以使用状态压缩进行求解。
- 参考leetcode中的桶放球模型,应该可以使用状态压缩dp来做。
- 如果扩展到n个数组,那么应该怎么做?使用状态压缩
- 出错debug:做一个随机数生成器与对拍器
收获
语法总结:
-
java中Integer列表转成Integer数组
(list.toArray(new Integer[list.size()]))
-
java中数组逆袭使用Collections.reverse()方法。
-
java中List排序的方法
Collections.sort()
或者list.sort(Integer::compareTo)
题目总结
见思考