目录
- 一、题目描述
- 二、输入描述
- 三、输出描述
- 四、补充说明
- 五、Java算法源码
- 六、效果展示
- 1、输入
- 2、输出
- 3、说明
一、题目描述
某网上商城举办优惠活动,发布了满减、打折、无门槛3种优惠券,分别为:
1.每满100元优惠10元,无使用数限制,如100199元可以使用1张减10元,200299可使用2张减20元,以此类推;
2.92折券,1次限使用1张,如100元,则优惠后为92元;
3.无门槛5元优惠券,无使用数限制,直接减5元。
每次最多使用2种优惠券,2种优惠可以叠加(优惠叠加时以优惠后的价格计算),以购物200元为例,可以先用92折券优惠到184元,再用1张满减券优惠10元,最终价格是174元,也可以用满减券2张优惠20元为180元,再使用92折券优惠到165(165.6向下取整)元,不同使用顺序的优惠价格不同,以最优惠价格为准。在一次购物中,同一类型优惠券使用多张时必须一次性使用,不能分多次拆开穿插使用(不允许先使用1张满减券,再用打折券,再使用一张满减券)。
请设计实现一种解决方法,帮助购物者以最少的优惠券获得最优的优惠价格。优惠后价格越低越好,同等优惠价格,使用的优惠券越少越好,可以允许某次购物不使用优惠券。
优惠活动每人只能参加一次,每个人的优惠券种类和数量是一样的。
二、输入描述
第一行:每个人拥有的优惠券数量(数量取值范围为[0, 10]),按满减、打折、无门槛的顺序输入。
第二行:表示购物的人数n(1 <= n <= 10000)。
最后n行:每一行表示某个人优惠前的购物总价格(价格取值范围(0, 1000],都为整数)。
约定:输入都是符合题目设定的要求的。
三、输出描述
每行输出每个人每次购物优惠后的最低价格以及使用的优惠券总数量,每行的输出顺序和输入的顺序保持一致。
四、补充说明
1.优惠券数量都为整数,取值范围为[0, 10]。
2.购物人数为整数,取值范围为[1, 10000]。
3.优惠券的购物总价为整数,取值范围为(0, 1000]。
4.优惠后价格如果是小数,则向下取整,输出都为整数。
五、Java算法源码
// 优惠后的最终价格
public static int lastPrice = Integer.MAX_VALUE;
// 分别使用优惠券数量
public static int[] couponCountArr = new int[3];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int[] coupons = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
// 满减个数
int fullReduction = coupons[0];
// 打折个数
int discounts = coupons[1];
// 优惠券数量
int coupon = coupons[2];
// 购物的人数
int n = Integer.valueOf(sc.nextLine());
int[] priceArr = new int[n];
for (int i = 0; i < n; i++) {
// 每一行表示某个人优惠前的购物总价格
int price = Integer.valueOf(sc.nextLine());
priceArr[i] = price;
}
// 根据每一行输入的优惠前的购物总价格,计算优惠价格
for (int i = 0; i < n; i++) {
calculate(priceArr[i], fullReduction, discounts, coupon);
}
}
/**
* 根据每一行输入的优惠前的购物总价格,计算优惠价格
*
* @param price 优惠前的购物总价格
* @param fullReduction 满减个数 每满100元优惠10元,无使用数限制
* @param discounts 打折个数 92折券 1次限使用1张
* @param coupon 优惠券数量 无门槛5元优惠券,无使用数限制
*/
public static void calculate(int price, int fullReduction, int discounts, int coupon) {
lastPrice = Integer.MAX_VALUE;
couponCountArr = new int[3];
int[] visited = new int[3];
dfs(price, fullReduction, discounts, coupon, visited, 0, price);
// 使用优惠券的总张数
int couponCount = 0;
for (int i = 0; i < couponCountArr.length; i++) {
couponCount += couponCountArr[i];
}
System.out.println(lastPrice+" "+couponCount);
}
/**
* 计算使用优惠券
* @param price 价格
* @param fullReduction 满减个数
* @param discounts 打折个数
* @param coupon 5元优惠券个数
* @param visited
* @param couponTimes 使用了几种优惠券
* @param calculatedPrice 优惠后价格
*/
public static void dfs(int price, int fullReduction, int discounts, int coupon, int[] visited, int couponTimes, int calculatedPrice) {
if (couponTimes == 2) {
if (calculatedPrice < lastPrice) {
lastPrice = calculatedPrice;
}
return;
}
for (int i = 0; i < visited.length; i++) {
if (visited[i] == 1) {
continue;
}
visited[i] = 1;
// 优惠后价格
// 使用几张优惠券
int[] couponArr = new int[2];
if (i == 0) {
// 满减个数 每满100元优惠10元,无使用数限制
couponArr = calculateFullReduction(calculatedPrice, fullReduction);
} else if (i == 1) {
// 打折
couponArr = calculateDiscounts(calculatedPrice, discounts);
} else {
// 使用5元优惠券
couponArr = calculateCoupon(calculatedPrice, coupon);
}
dfs(price, fullReduction, discounts, coupon, visited, couponTimes + 1, couponArr[0]);
visited[i] = 0;
}
}
/**
* 满减个数 每满100元优惠10元,无使用数限制
* @param price 当前价格
* @param fullReduction 满减优惠券个数
* @return
*/
public static int[] calculateFullReduction(int price, int fullReduction) {
// 使用满减优惠券的个数
int a = Math.min(fullReduction, price / 100);
// 用满减之后的价格
int preferentialPrice = price;
// 使用满减优惠券的个数
int fullReductionUsed = 0;
for (int i = 0; i < a; i++) {
if (preferentialPrice > 0) {
preferentialPrice -= 10;
fullReductionUsed++;
}
}
// preferentialPrice:使用满减之后的价格
// fullReductionUsed:可以使用几张满减优惠券
return new int[]{preferentialPrice, fullReductionUsed};
}
/**
* 打折个数 92折券 1次限使用1张
* @param price 当前价格
* @param discounts 打折优惠券使用个数
* @return
*/
public static int[] calculateDiscounts(int price, int discounts) {
// 1次限使用1张
int discountsCount = Math.min(1, discounts);
int discountsPrice = price;
int discountsUsed = 0;
for (int i = 0; i < discountsCount; i++) {
if (discountsPrice > 0) {
discountsUsed++;
discountsPrice *= 0.92;
}
}
// discountsPrice:打折后的价格
// discountsUsed:可以使用几张打折优惠券
return new int[]{discountsPrice, discountsUsed};
}
/**
* 优惠券数量 无门槛5元优惠券,无使用数限制
* @param price 当前价格
* @param coupon 优惠券数量
* @return
*/
public static int[] calculateCoupon(int price, int coupon) {
// 使用couponUsed张5元优惠券之后的价格
int couponPrice = price;
// 使用几张5元优惠券
int couponUsed = 0;
// 使用coupon张5元优惠券
for (int i = 0; i < coupon; i++) {
if (couponPrice > 0) {
couponUsed++;
couponPrice -= 5;
}
}
// discountsPrice:使用couponUsed张5元优惠券之后的价格
// couponUsed:使用几张5元优惠券
return new int[]{Math.max(couponPrice, 0), couponUsed};
}
六、效果展示
1、输入
3 2 5
3
100
200
400
2、输出
65 6
155 7
338 4
3、说明
输入3个人,输出3行结果,同输入的顺序,对应每个人的优惠结果,如下:
第一行:先使用1张满减券优惠到90元,再使用5张无门槛券优惠25元,最终价格是65元,总共使用6张优惠券
第二行:先使用2张满减券优惠到180元,再使用5张无门槛券优惠25元,最终价格是155元,总共使用7张优惠券
第三行:先使用1张92折券优惠到368元,再使用3张满减券优惠30元,最终价格是338元,总共使用4张优惠券
🏆下一篇:华为OD机试真题 Java 实现【跳房子II】【2023 B卷 100分】,附详细解题思路
🏆本文收录于,华为OD机试(JAVA)(2022&2023)
每一题都有详细的答题思路、详细的代码注释、样例测试,订阅后,专栏内的文章都可看,可加入华为OD刷题群(私信即可),发现新题目,随时更新,全天CSDN在线答疑。