首页 > 试题广场 >

矿泉水问题

[编程题]矿泉水问题
  • 热度指数:2017 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解

小明横穿沙漠,需要携带至少x毫升的水。

有两种规格的矿泉水可供选购:小瓶矿泉水每瓶500ml,价格a元。大瓶矿泉水每瓶1500ml,价格b元。

小明打算买一些矿泉水用于横穿沙漠,为了保证至少买到x毫升的水,小明至少需要花费多少钱?


输入描述:
第一行一个正整数t(t<=1000),表示有t组测试数据;

接下来t行,每行3个正整数:x,a,b。其中x<=1,000,000,000,表示小明至少需要x毫升水;a<=100,b<=100,分别表示小瓶和大瓶矿泉水的价格,单位:元。


输出描述:
每组测试数据输出一行,表示小明最少需要花费的钱,单位:元。
示例1

输入

3
5000 5 10
4999 5 10
5000 5 100

输出

35
35
50
  1. 首先判断每1500毫升,使用500ml*3便宜还是直接买1500ml便宜
    • 哪个便宜就用哪个组成1500ml
  2. 可能剩下的不满足1500ml: 判断使用多个500ml来填充剩下的,还是直接买一瓶1500ml的。哪个便宜选哪种
    import math
    class Solution():
     def f(self,x,a,b):
         a3=3*a
         min_p=min(a3,b)
         base_p=x//1500*min_p
         rest=x%1500
         use_a=math.ceil(rest/500)*a
         rest_p=min(use_a,b)
         return base_p+rest_p
    n=int(input().strip())
    sol=Solution()
    for i in range(n):
     line=[int(item) for item in input().strip().split()]
     res=sol.f(*line)
     print(res)
发表于 2020-06-28 21:26:24 回复(0)
#include<iostream>
#include<string>
#include<math.h>

using namespace std;



// x , a(500), b(1500)
int solution(int x, int a, int b){
    if(a * 3 <= b){     // 如果买小瓶的更加划算那就全部购买小瓶的
        return ceil(x/(double)500) * a;
    }
    int ret = (x / 1500) * b;     // 买大瓶的
    int reminds = ceil((x % 1500) / (double)500) * a;       // 剩余需要购买的
    return ret + min(reminds, b);;
}


int main(){
    int n;
    cin >> n;
    int ret[n];
    for(int i = 0; i < n; i++){
        int x, a, b;
        cin >> x >> a >> b;
        ret[i] =  solution(x, a, b);
    }
    for(int i = 0; i < n; i++){
        cout << ret[i] << endl;
    }
}

发表于 2022-08-11 20:02:29 回复(0)
/*
* 分享一个java的代码
* 思路:
* 1.判断性价比:如果大瓶的价格是小瓶的三倍或更多,那肯定全选小瓶,反之则进入第二步判断
* 2.判断最后一个大瓶是否用1至2个小瓶替代,看看几个小瓶替代的后的总价格是否超过一个大瓶的价格,是则替代,否则替代
* */


import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int swml=500;
        int bwml=1500;
        //a[x][0]为最小ml
        //a[x][1]为小瓶价格
        //a[x][2]为大屏价格
        int tem= in.nextInt();
        int a[][] = new int[tem][3];
        for(int i=0;i<tem;i++){
            for(int j=0;j<3;j++){
                a[i][j]=in.nextInt();
            }
        }
        double b[]=new double[tem];
        for(int i=0;i<tem;i++){
            b[i]=(double)a[i][2]/(double)a[i][1];
            //性价比小于3;小瓶优势
            if(3-b[i]<1e-12){
                int n = 0;
                while (n*swml<a[i][0]){
                    n++;
                }
                System.out.println(n*a[i][1]);
            }
            //大瓶优势
            else {
                int n=0;
                while (n*bwml<a[i][0]){
                    n++;
                }
                //全部都是大瓶的价格
                int n1=n*a[i][2];
                //开始用小瓶替代最后一个大瓶
                int m=0;
                while (((n-1)*bwml+m*swml)<a[i][0]){
                    m++;
            }
                //小瓶替代后的价格
                int n2=(n-1)*a[i][2]+m*a[i][1];
                //判断谁便宜就可以了
                if(n1<n2) System.out.println(n1);
                else System.out.println(n2);
            }
        }
    }
}

发表于 2023-09-20 22:18:33 回复(0)
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int num = sc.nextInt();
        for (int i = 0; i < num; i++) {
            System.out.println(takeMoney(sc.nextInt(), sc.nextInt(), sc.nextInt()));
        }
    }
    public static int takeMoney(int x, int smallMoney, int bigMoney) {
        double smallCostPerformance = (double)smallMoney / 500;
        double bigCostPerformance = (double)bigMoney / 1500;        //每毫升单价
        //firstBuy为true则代表小瓶水性价比高
        //firstBuy为false则代表大瓶水性价比高
        boolean firstBuy = bigCostPerformance > smallCostPerformance;
        int curWater;                                   //已购买的水
        int bigNum;
        int smallNum;
        if (firstBuy){
            //优先购买小瓶水
            smallNum = x / 500;
            curWater = smallNum * 500;
            if (curWater == x) return smallNum * smallMoney;
            else return smallNum * smallMoney + smallMoney;
        } else {
            //优先购买大瓶水
            bigNum = x / 1500;
            curWater = bigNum * 1500;
            if (curWater == x) return bigNum * bigMoney;
            else {
                smallNum = (x - curWater) % 500 == 0 ? (x - curWater) / 500 : (x - curWater) / 500 + 1;
                return bigNum * bigMoney + Math.min(smallMoney * smallNum, bigMoney);
            }
        }
    }
}

编辑于 2022-09-01 14:57:57 回复(0)
n = int(input())
for _ in range(n):
    x, a, b = map(int, input().split())
    min_p = min(3*a, b)
    base = x//1500*min_p
    leave = x%1500
    print(base + min(b, ((leave-1)//500+1)*a)) 
    #(leave-1) 可以减少说明的情况
    # 当 leave刚好等于500的整数倍时,(leave-1)//500+1 就是所需要的矿泉水瓶数
    
    
        

发表于 2020-09-17 16:57:37 回复(0)
import math
t = int(input())
for _ in range(t):
    min_money = 0
    a,b,c = list(map(int,input().split()))
    part_1 = (a // 1500) * min(3*b,c)
    part_2 = min(c,math.ceil((a%1500)/500) * b)
    print(part_1 + part_2)

发表于 2020-08-25 17:57:11 回复(0)
import math
T = int(input())
ans = []
for t in range(T):
    water, a, b = [int(item) for item in input().strip().split()]
    if b > a * 3: # 只买小瓶水划算
        #price = water // 500 * a if water % 500 == 0 else (water // 500 + 1)* a
        #price = math.ceil(water / 500) * a
        price = ((water - 1) // 500 + 1) * a
    elif b <= a * 3: # 只买大瓶水划算,但是要看买了大瓶水之后的余数 和小瓶水比较一下 
        price = water // 1500 * b
        r = water % 1500
        #price = price + min(b, math.ceil(r / 500) * a)
        price = price + min(b,((r - 1)// 500 + 1) * a)
    print(price)
'''题解区大佬  并没有使用 math.ceil()函数,而是用 ((water-1)// 500 + 1)  巧妙的可以得到和ceil一样的结果 '''

发表于 2020-08-25 17:20:02 回复(0)
#include <iostream>
using namespace std;
int main()
{
    int n=0;
    while(cin>>n)
    {
        while(n--)
        {
            int x,a,b;
            cin>>x>>a>>b;
            int sum=0;
            sum+=x/1500*min(b,3*a);
            int res=x%1500;
            if(res>0)
            {
                if(res<=500)
                    sum+=min(a,b);
                else if(res<=1000)
                    sum+=min(2*a,b);
                else
                    sum+=min(3*a,b);
            }
            cout<<sum<<endl;
        }
    }
    return 0;
}

发表于 2020-08-13 21:13:41 回复(0)
python 全部通过
import math
num_input = int(input())

for i in range(num_input):
    water = [int(j) for j in input().split()]

    ratio = (water[1]/500)/(water[2]/1500)
    not_enough = water[0] - water[0] // 1500 * 1500

    if ratio <= 1:  # 说明500ml的水便宜,可全买
        sum_price = math.ceil(water[0]/500)*water[1]
    elif 1 < ratio <= 1.5:  # 说明1500毫升的水便宜,1000ml以内时,就买500ml
        if not_enough <= 1000:
            sum_price = water[0]//1500*water[2] + math.ceil(not_enough/500)*water[1]
        else:
            sum_price = math.ceil(water[0]/1500)*water[2]
    elif 1.5 < ratio <= 3:  # 说明1500毫升的水便宜,500ml以内时,就买500ml
        if not_enough <= 500:
            sum_price = water[0] // 1500 * water[2] + water[1]
        else:
            sum_price = math.ceil(water[0] / 1500) * water[2]
    else:
        sum_price = math.ceil(water[0] / 1500) * water[2]

    print(sum_price)

发表于 2020-08-12 10:35:42 回复(0)
N = int(input())
for _ in range(N):
    x, a, b = list(map(int, input().strip().split()))
    part1 = (x//1500) * min(3 * a, b)
    part2 = min(b, (x % 1500) // 500 * a + a * ((x % 1500) % 500 > 0))
    print(part1 + part2)

发表于 2020-08-03 23:36:42 回复(0)
全买小水的,超过最大值怎么不考虑
发表于 2020-07-18 16:50:24 回复(0)
开始下意识用dp数组,结果有误
'''
买三瓶小水价格3a和卖一瓶大水的价格b,若3a<b,则必定全部买小水
若大水便宜,则1.全部买大瓶;2.能买大水的部分买大水,其余用小水,选择1和2中较小值
'''
def cost(x,a,b):
    if 3*a<b:
        # 全部买小水,需要瓶数
        n = x//500+1 if x%500 != 0 else x//500
        return n*a
    else:
        # 买大水瓶数
        m = x//1500+1 if x%1500 != 0 else x//1500
        # 1. 全买大瓶
        cost1 = m*b
        # 2. 尽可能买大瓶,剩下买小的
        x = x-1500*(m-1)
        n = x//500+1 if x%500 != 0 else x//500
        cost2 = (m-1)*b+n*a
        return min(cost1,cost2)
        
while True:
    try:
        n = int(input())
        for i in range(n):
            [x,a,b] = list(map(int,input().split()))
            print(cost(x,a,b))
    except:
        break

发表于 2020-06-26 17:52:24 回复(2)
思路:一瓶大的等于三瓶小的水量,如果小瓶便宜必定全买小瓶,如果大瓶便宜, 
先全部买大瓶,再考虑去掉最后一瓶买小瓶是否划算。
为什么不需要考虑用 更多的大瓶换成小瓶?
因为除了最后一瓶大瓶,其它大瓶的水量总和都是在x以内的,也就是必须要买的,
既然是必须要买,而大瓶更划算当然是买大瓶。
编辑于 2020-06-19 09:11:21 回复(0)
#include <iostream>
using namespace std;
int main(void)
{
	int T = 0;
	while (cin >> T)
	{
		while (T--)
		{
			long long total = 0, sprice = 0, bprice = 0, temp = 0, leastcost = 0;
			cin >> total >> sprice >> bprice;
			//判断单位性价比
			if (sprice * 3 == bprice)//性价比相同
			{
				if (total % 500 == 0)//全买小瓶
				{
					leastcost = total / 500 * sprice;
				}
				else
				{
					leastcost = (total / 500 + 1)*sprice;
				}
			}
			else if (sprice * 3> bprice)//买大瓶性价比高
			{
				if (total % 1500 == 0)
				{
					//全买大瓶
					leastcost = total / 1500 * bprice;
				}
				else
				{
					//三种可能:1 全买大瓶 2 只有一个小瓶其他大瓶 3只买两个小瓶其他大瓶
					int allbigPrice = (total / 1500 + 1)*bprice;
					int rest = total - total / 1500 * 1500;//剩下的容量
					if (rest <= 500)
					{
						temp = total / 1500 * bprice + sprice;//只买一瓶小瓶
						if (temp > allbigPrice)
							leastcost = allbigPrice;
						else leastcost = temp;
					}
					else if (rest <= 1000)
					{
						temp = total / 1500 * bprice + 2 * sprice;//只买两瓶小瓶
						if (temp > allbigPrice)
							leastcost = allbigPrice;
						else leastcost = temp;
					}
					else
					{
						leastcost = allbigPrice;
					}
				}
			}
			else//小瓶性价比高
			{
				if (total % 500 == 0)//全买小瓶
				{
					leastcost = total / 500 * sprice;
				}
				else
				{
					int allsmallPrice = (total / 500 + 1)*sprice;//全买小瓶
					//只买一瓶大瓶
					int onebigPrice = (total / 500 - 2)*sprice + bprice;//大瓶可以抵掉两瓶小瓶
					if (onebigPrice > allsmallPrice)
						leastcost = allsmallPrice;
					else leastcost = onebigPrice;

				}
			}
			cout << leastcost << endl;

		}

	}
	return 0;
}

发表于 2020-06-16 11:57:14 回复(1)
第一次用python写,犯了一错误,在获得输入时用了x=int(input()), a=int(input()),b=int(input())来获得,这样在获取时只能获得换行输入的,不能得到一行中输入的多个数字,导致代码一直没有通过,找了半天才弄明白原来是这儿出错了。后改为x,a,b=map(int,input().split())来获得一行的输入。
t=int(input())
for _ in range(t):
    x, a, b = map(int, input().split())
    m_a=x//500
    n_b=x//1500
    cos=1e9
    if(3*a<=b):
        if(x%500!=0):
            m_a=m_a+1
        print(m_a*a)
    else:
        for n in range(n_b,n_b+2):
            for m in range(0,3):
                if(m*500+n*1500>=x):
                    if((m*a+n*b)<cos):
                        cos=m*a+n*b
                        break
        print(cos)

发表于 2020-06-15 10:56:58 回复(0)
for _ in range(int(input())):
    x, a, b = map(int, input().split())
    p, x = divmod(x, 1500)
    print(p * min(b, a * 3) + min((x != 0) * b, (x + 499) // 500 * a))

发表于 2020-06-14 15:10:09 回复(0)
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        ll x,a,b,w=0;
        cin>>x>>a>>b;
        if(3*a<=b)
        {
            if(x%500==0)
                w=x/500*a;
            else
                w=x/500*a+a;
        }
        else
        {
            if(x%1500==0)
                w=x/1500*b;
            else
            {
                if(x%1500<=500)
                {
                    if(a<=b)
                        w=x/1500*b+a;
                    else
                        w=x/1500*b+b;
                }
                else if(x%1500<=1000)
               {
                     if(2*a<=b)
                         w=x/1500*b+2*a;
                    else
                        w=x/1500*b+b;
               }
                else
                {
                    w=x/1500*b+b;
                }
            }
        }
         cout<<w<<endl;
    }
    return 0;
}
发表于 2020-05-30 11:42:13 回复(0)
import java.util.Scanner;
public class Main{
    public static void main(String[] args){
        Scanner sc=new Scanner((System.in));
        int group=sc.nextInt();
        int arr[][]=new int[group][3];
        int sum[]=new int[group];
        for(int i=0;i<group;i++){
            for(int j=0;j<3;j++){
                arr[i][j]=sc.nextInt();
            }
        }
       for(int i=0;i<group;i++){
           if(3*arr[i][1]<=arr[i][2]){
               sum[i]= (int) (Math.ceil(arr[i][0]/500.0)*arr[i][1]);
           }
           else if (arr[i][1]>=arr[i][2]){
               sum[i]=(int)(Math.ceil(arr[i][0]/1500.0)*arr[i][2]);
           }
           else {
               int b = (int) Math.floor(arr[i][0] / 1500.0);
               int a = (int) Math.ceil((arr[i][0]-b*1500)/500.0);
               sum[i] = arr[i][1] * a + arr[i][2] * b;
           }
       }
        for(int i=0;i<group;i++){
            System.out.println(sum[i]);
        }
    }
}
我这个明明200个测试样例都能通过,为什么case通过率是0呢?新手求大佬解答
编辑于 2020-05-28 14:33:56 回复(1)
import math
n=int(input())
for _ in range(n):
    x,a,b=map(int,input().split())
    x,base=x%1500,x//1500
    base= base*3*a if 3*a<=b else base*b
    base+= min(b,math.ceil(x/500)*a)
    print(base)
    
发表于 2020-05-26 09:33:14 回复(0)
import math


t = int(input("请输入样本个数: "))

min_money = 99999999
while t>0:
    # x = int(input("请输入需要多少毫升水:"))
    # a = int(input("请输入小瓶水的价格:"))
    # b = int(input("请输入大瓶水的价格:"))
    # 这样x,a,b均为int型,且输入间隔为空格
    x, a, b = map(int, input().split())


    # lists = []


    for a_num in range(0, math.ceil(x/500)+1):
        count = a_num*a + math.ceil((x-a_num*500)/1500)*b
        # lists.append(count)
        if min_money>count:
            min_money=count
    # lists.sort()
    # print(lists[0])
    # print(lists)
    print(min_money)

    t = t - 1
    min_money = 99999999




发表于 2020-05-26 00:00:47 回复(2)