【题目描述】 给一个包含 n个整数元素的集合 个整数元素的集合 a,一个包含 m个整数元素的集合 b。
定义 magic操作为,从一个集合中取出元素放到另里且过后每的平均值都大于操作前。
注意以下两点:
①不可以把一个集合的元素取空,这样就没有平均值了
②值为 x的元素从集合 b取出放入集合a,但集合 a中已经有值为 x的元素,则 a的平均值不变(因为集 合元素不会重复), b的平均值可能会改变(因为 x被取出了)
问最多可以进行少次 magic操作
输入:
3 5
1 2 5
2 3 4 5 6
输出:
2
1、深度优先搜索
package ZiJieTiaoDong;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Scanner;
public class MoveMagic {
static int N = 0;
static int M = 0;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
N = n;
M = m;
HashSet<Integer> setA = new HashSet<>();
ArrayList<Integer> list = new ArrayList<>();
double sumA = 0;
double sumB = 0;
int a = 0;
for (int i = 0; i < n; i++) {
a = sc.nextInt();
setA.add(a);
sumA += a;
}
for (int i = 0; i < m; i++) {
a = sc.nextInt();
list.add(a);
sumB += a;
}
double aveA = sumA / n;
double aveB = sumB / m;
dfs(sumA, sumB, aveA, aveB, setA, list);
System.out.println(count);
}
static int count = 0;
public static void dfs(double sumA, double sumB, double aveA, double aveB, HashSet<Integer> setA,
ArrayList<Integer> list) {
if (list.size() == 0) {
count = list.size() - 1;
return;
}
int n = setA.size();
int m = list.size();
for (int i = 0; i < list.size(); i++) {
int value = list.get(i);
if ((sumA + value) / (n + 1) > aveA && (sumB - value) / (m - 1) > aveB) {//满足要求
setA.add(value);
list.remove(i);
aveA = (sumA + value) / (n + 1);
aveB = (sumB - value) / (m - 1);
dfs(sumA + value, sumB - value, aveA, aveB, setA, list);//操作后,递归
list.add(i, value);//未操作
if (setA.size() == n + 1) {
setA.remove(value);
}
aveA = sumA / n;
aveB = sumB / m;
}
}
if (M - list.size() > count) {
count = M - list.size();
}
}
}
2、迭代
从平均值大的team_a中取出比team_a平均值小且比team_b大的最小元素放入team_b中
def compete(team_a, team_b):
def find_min(team_a, ave_a, ave_b):
# 查找可以动的数值
if len(team_a) == 1:
return -1
for a in sorted(team_a):
if ave_b < a < ave_a:
return a
return -1
team_a, team_b = set(team_a), set(team_b) # 转换成集合
n, m = len(team_a), len(team_b) # 计算长度
sum_a, sum_b = sum(team_a), sum(team_b) # 计算和
ave_a, ave_b = sum_a / n, sum_b / m # 计算平均值
if ave_a < ave_b: # 交换team_a,和team_b, 保持team_a永远是平均值大的那个
team_a, team_b = team_b, team_a
ave_a, ave_b = ave_b, ave_a
sum_a, sum_b = sum_b, sum_a
n, m = m, n
min_val = find_min(team_a, ave_a, ave_b) # 查找可以动的数值
res = 0
while min_val != -1:
team_a.remove(min_val) # team_a中取出
team_b.add(min_val) # team_b中加入
# 更新数值
sum_a -= min_val
sum_b += min_val
n -= 1
m += 1
ave_a, ave_b = sum_a / n, sum_b / m
res += 1
if ave_a < ave_b: # 保持team_a永远是平均值大的那个
team_a, team_b = team_b, team_a
ave_a, ave_b = ave_b, ave_a
sum_a, sum_b = sum_b, sum_a
n, m = m, n
min_val = find_min(team_a, ave_a, ave_b) # 重新查找可以动的数值
return res