趣味算法之怎样订饭最省钱

近来很多同事都在网上订餐,网上订餐基本都会有优惠,不同家的优惠策略不同,但大体上都是三种策略,比如有几家是满15减6,满30减15,满50减20。

然后我突发奇想,何不写个程序,来根据餐厅的优惠政策计算下怎样拼饭最省钱呢?于是有了下面代码:


import java.util.ArrayList;
import java.util.Scanner;

public class Lunch {

	public static double[] Fee = {15, 30, 50};//满多少钱可优惠
	public static double[] Dis = {6, 15, 20};//对应的优惠价格

	public static double[] disCount;//折扣
	public static int[] strategy;//策略
	public static int[] price;//每份饭的单价
	public static int[] priceCopy;//同样是每份饭的单价
	public static double sumPrice = 0.0;//优惠前的总价
	public static int person = 0;//共几人订餐

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		person = sc.nextInt();
		price = new int[person];
		priceCopy = new int[person];
		for(int i=0; i<person; i++){
			price[i] = sc.nextInt();
			priceCopy[i] = price[i];
			sumPrice += price[i];
		}
		disCount = new double[3];
		strategy = new int[3];
	    for(int i=0; i<3; i++){
	    	disCount[i] = Dis[i]/Fee[i];
	    }
		double max = 0.0;
		int maxIndex = 0;
		
		for(int i=0; i<3; i++){
			max = disCount[i];
			maxIndex = i;
			for(int j=0; j<3; j++){
				if(disCount[j] > max){
					max = disCount[j];
					maxIndex = j;
				}
			}
			strategy[i] = maxIndex;
			disCount[maxIndex] = 0;
		}
		double save = cal();
		System.out.println("总共省钱"+save+"元");
		sc.close();
	}
	/**
	 * 返回节约的饭钱
	 * straNum 是指当前使用的打折策略的编号
	 * save 是指已经节省的钱
	 * */
	private static double cal() {
		double save = 0.0;
		int straNum = 0;
		ArrayList<Integer> choosed = new ArrayList<Integer>();
		
		while(straNum < 3){
			int index = strategy[straNum];
			double pinPrice = Fee[index];
			if(sumPrice < pinPrice){
				straNum++;
				continue;
			}
			choosed = new ArrayList<Integer>();
			for(int add=0; true; add++){
				if(sumPrice < pinPrice + add){
					straNum++;
					break;
				}	
				
				if(choose(pinPrice+add, 0, choosed)){
					sumPrice -= (pinPrice+add);
					save += Dis[index];
					System.out.println("此单凑出的钱数为:"+(pinPrice+add));
					System.out.print("由以下价格凑出:");
					for(int c:choosed){
						System.out.print(priceCopy[c]+" ");
					}
					System.out.println();
					break;
				}else{
					int nextIndex = strategy[straNum+1];
					double nextFee = Fee[nextIndex];
					double nextDis = Dis[nextIndex];
					int counts = (int) (((pinPrice+add)/nextFee)%1);
					double nextSave = nextDis * counts;
					if(nextSave > Dis[index]){
						straNum++;
						break;
					}
				}
			}
		}
		return save;
	}
	/**
	 * 返回是否能拼出饭钱pinPrice
	 * @param pinPrice 要拼的饭钱
	 *        cur 当前要处理的餐费
	 *        choosed 存放被选择的餐费的下标
	 * */
	private static boolean choose(double pinPrice, int cur, ArrayList<Integer> choosed){
		
		if(pinPrice < 0)
			return false;
		while(cur<person && price[cur]==0){
			cur++;
		}
		if(cur == person && pinPrice!=0)
			return false;
		if(pinPrice ==0 ){
			return true;
		}
		if(choose(pinPrice - price[cur], cur+1, choosed)){
			choosed.add(cur);
			price[cur] = 0;
			return true;
		}else if(choose(pinPrice, cur+1, choosed)){
			return true;
		}else{
			return false;
		}

	}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

热血大婶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值