题目描述:有n位小朋友去小明家里拜年,小明准备了m份礼物。小明想把所有礼物平均分给每个小朋友,每个小朋友得到相同个数的礼物。但是m未必能被n整除,小明可以使用以下两种操作任意多次(两种操作可以同时使用)。
1、 给其中一个小朋友发红包,收到红包的小朋友会离开小明家。每个红包需要花费a元。
2、 购买一个新礼物,每个礼物价值为b元。
问小明最少花费多少元,才能使得所有礼物可以被剩下的小朋友平分。
输入
第一行输入四个整数n,m,a,b(1≤n,m,a,b≤100)。
输出
输出最少花费。
样例输入
7 5 10 100
样例输出
20
提示
输入样例2
2 2 10 10
输出样例2
0
输入样例3
3 1 10 10
输出样例3
20
样例解释
样例一发两个红包。样例二不需要任何操作。样例三买两个新礼物,或者发两个红包,或者发一个红包买一个新礼物。
解析
作者:Galliano、
链接:https://www.nowcoder.com/discuss/403152?type=all&order=time&pos=&page=1
来源:牛客网
/**
* 微众 第 1 题,最小花费问题
*/
public static void main1(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(); // n个小朋友
int m = sc.nextInt(); // m份礼物
int a = sc.nextInt(); // 每个红包的花费
int b = sc.nextInt(); // 每个礼物的价值
sc.close();
System.out.println(minCost(n, m, a, b));
}
private static int minCost(int n, int m, int a, int b) {
if (n > m) { // 当人数大于礼物数时
// 此时对于 (人数和礼物数) 的差值,要么发红包,要么买新礼物,且 红包数+新礼物数 = n - m
// 此时当然是选 单个红包和礼物中较便宜的那个。
return (n - m) * Math.min(a, b);
} else if (m % n == 0){ // 当可以完全均分时,不需要额外花钱
return 0;
} else { // 其他情况为:当人数小于礼物数时,且不能完全均分时
// 列出线性规划方程
// n:总客人数, m:总礼物数
// x:离开多少人,y:买多少礼物,k的目的是:让礼物能完全均分,k必须是自然数
// 方程1:k * (n - x) = m + y
// 方程2:minCost = x * a + y * b,求能使minCost最小的 x 和 y。
int res = Integer.MAX_VALUE;
// redPacketNum代表发几个红包,最多只需要发 n-1 个红包
for (int redPacketNum = 1; redPacketNum < n; redPacketNum++) {
// 求出当发 redPacketNum 个红包时,需要买的礼物数 buyGiftNum
if (m % (n - redPacketNum) == 0) {
res = Math.min(res , redPacketNum * a);
} else {
int buyGiftNum = (m / (n - redPacketNum) + 1) * (n - redPacketNum) - m;
res = Math.min(res , redPacketNum * a + buyGiftNum * b);
}
}
return res;
}
}