网上商城优惠活动【C语言】

/*
【逻辑分析】
某网上商场举办优惠活动,发布了满减、打折、无门槛3种优惠券,分别为;
1:每满100元优惠10元,无使用数限制,如100~199元可以使用1张减10元,200~299可使用2张减20元,以此类推;
2:92折券,1次限使用1张,如100元,则优惠后为92元,
3:无门槛5元优惠券,无使用数限制,直接减5元。

优惠券使用限制:每次最多使用2种优惠券,2种优惠可以叠加(优惠叠加时以优惠后的价格计算)。
    以购物20O元为例,可以先用92折券优惠到184元,再用1张满减券优惠10元,最终价格是174元,
也可以用满减券2张优惠20元为180元,再使用92折券优惠到165(165.6向下取整Q),不同使用顺序的优惠价格不同,以最优惠价格为准。
在一次购物中,同一类型优惠券使用多张时必须一次性使用,不能分多次拆开使用(不允许先使用1张满减券,再用打折券,再使用一张满减券)。
    请设计实现一种解决方法,帮助购物者以最少的优惠券获得最优的优惠价格。
优惠后价格越低越好,同等优惠价格,使用的优惠券越少越好,可以允许某次购物不使用优惠券。
    约定:优惠活动每人只能参加一次,每个人的优惠券种类和数量是一样的。
输入描述
1:第一行:每个人拥有的优惠券数量(数量取值范围为[0,10],按满减、打折、无门槛的顺序输入
2:第二行:表示购物的人数n(1≤n≤10000)
3:最后n行:每一行表示某个人优惠前的购物总价格(价格取值范围(0,1000],都为整数)。
输出描述
1:每行输出每个人每次购物优惠后的最低价格以及使用的优惠券总数量。每行的输出顺序和输入的顺序保持一致备注
备注
1.优惠券数量都为整数,取值范围为[0,10]
2.购物人数为整数,取值范围为[1,10000]
3.优惠券的购物总价为整数,取值范围为(0.1000]
4.优惠后价格如果是小数,则向下取整,输出都为整数。
示例1:
3 2 5
3
100
200
400
输出
65 6
155 7
338 4
*/

//思路:无门槛卷一定最后用,所以有4种先后顺序
//满减+打折,打折+满减,满减+无门槛,打折+无门槛
//每种写个函数,把结果price和count存在一个二位数组中
//用qsort函数排序,注意此时传进函数的是一个二维数组,cmpfunc要重写

#include <stdio.h>
#include <stdlib.h>
 
#define MIN(a, b) ((a) < (b)) ? (a) : (b)
#define MAX(a, b) ((a) > (b)) ? (a) : (b)
 
//一位数组快排函数
int cmpfunc (const void * a, const void * b) {//传进来的是一位数组首元素的地址
   return ( *(int*)a - *(int*)b );
}

//模仿一维写的二维数组快排函数
//当price_a != price_b时,按照price排
//当price_a = price_b时,按照count排
int cmpfunc_2(const void *a, const void *b){//传进来的是二维数组每一行首元素的地址
	if(((int*)a)[0] != ((int*)b)[0])
		return ((int*)a)[0] - ((int*)b)[0];
	else if(((int*)a)[0]==((int*)b)[0]){
			if(((int*)a)[1]>((int*)b)[1]) 
				return -1;
	}
	return 1;
}
 
int result[4][2];
 
//先满减后打折
void mode_a(int price, int m, int n) {
    int count = 0;
    count += MIN(m, (int)(price / 100));
    price -= count * 10;
    price *= 0.92;
    count += 1;
    
    result[0][0] = price;
    result[0][1] = count;
}
 
//先打折后满减
void mode_b(int price, int m, int n) {
    int count = 0;
 
    price *= 0.92;
    count += 1;
 
    count += MIN(m, (int)(price / 100));
    price -= (count-1) * 10;
    
    result[1][0] = price;
    result[1][1] = count;
}
 
//先满减后无门槛
void mode_c(int price, int m, int k) {
    int count = 0;
 
    count += MIN(m, (int)(price / 100));
    price -= count * 10;
    for (int i=0;i<k;i++) {
        price -= 5;
        count += 1;
        if (price <0) {
            break;
        }
    }
    
    result[2][0] = price;
    result[2][1] = count;
}
 
//先打折后无门槛
void mode_d(int price, int n, int k) {
    int count = 0;
 
    price *= 0.92;
    count += 1;
 
    for (int i=0;i<k;i++) {
        price -= 5;
        count += 1;
        if (price < 0) {
            break;
        }
    }
    result[3][0] = price;
    result[3][1] = count;
}
 
int main()
{
    int m,n,k;
    scanf("%d %d %d", &m,&n,&k);
    int x;
    scanf("%d", &x);
    int price[x];
    for (int i=0;i<x;i++) {
        scanf("%d", &price[i]);
    }
    for(int i=0;i<x;i++){
        mode_a(price[i], m, n);
        mode_b(price[i], m, n);
        mode_c(price[i], m, k);
        mode_d(price[i], n, k);
 
        //按照价格降序,用券数降序排序
        qsort(result, 4, sizeof(int) * 2, cmpfunc_2);
 
        printf("%d %d\n",result[0][0], result[0][1]);
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值