codechef December Challenge 2012 Pizza Delivery 完全背包求最小值 这道很重

文章探讨了如何通过最优的加油策略,最小化摩托车配送员的加油次数,从而提高送餐效率。通过分析不同加油站的加油能力与顾客位置的距离,提出了一种基于背包问题的解决方案,旨在最小化完成所有订单所需的加油次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Pizza Delivery

Problem code: DBOY

Chef Po had recently started home delivery service for pizzas. Po has only a single delivery boy that delivers the orders by riding his motorcycle. The motorcycle has an unlimited capacity of fuel tank. However, it is too old and can only ride 1 km for each 1 liter of fuel.

There are N fuel stations near the restaurant. The i-th fuel station can fill a fuel tank exactly Ki liters; not more and not less. Filling a fuel tank with any amount of fuel in those stations tends to take a long time. Since the fuel stations are placed near the restaurant, no fuel is needed to go to a fuel station.

Today Chef Po received N pizza orders, which is the same number of fuel stations fortuitously. The house of the person that ordered the i-th order is Hi km away from the restaurant. The delivery boy cannot deliver more than one order at a time. Therefore, after delivering an order, he must return back to the restaurant to take the next order.

The delivery boy is an efficient person and thus he wants to fill the fuel tank with the exact amount of fuel required to deliver an order and return back. He also does not want to spends much time filling the tank, so he wants to minimize the number of times he fills the tank. Help him determine the minimum number of times he must fill the tank to deliver all orders.

Input

The first line contains a single integer T denoting the number test cases. The description of T test cases follows. For each test case, the first line contains a single integer N. The second line contains N space-separated integers Hi. The third line contains N space-separated integers Ki.

Output

For each test case, output a single line containing the minimum number of times the delivery boy must fill the tank.

Constraints

1 ≤ T ≤ 500
1 ≤ N ≤ 500
1 ≤ Hi ≤ 500
1 ≤ Ki ≤ 500
There is at least one way for completing the deliveries.
That is, the delivery boy always can fill a fuel tank exactly 2 * Hi liters for 1 ≤ iN.

Example

Input:

1
4
1 2 3 4
1 4 5 3

Output:

7

Explanation:

Here is one possible solution.

For the first order, the delivery boy must ride 1 + 1 = 2 km long. Fill the tank twice in the first fuel station.

For the second order, the delivery boy must ride 2 + 2 = 4 km long. Fill the tank once in the second fuel station.

For the third order, the delivery boy must ride 3 + 3 = 6 km long. Fill the tank twice in the fourth fuel station.

For the fourth order, the delivery boy must ride 4 + 4 = 8 km long. Fill the tank in the third and fourth fuel stations.

In total, the delivery boy must fill the tank 7 times. There is no way to fill the tank less than 7 times.

http://www.codechef.com/DEC12/problems/DBOY/

题意

输入cas  输入n  输入n个h[i]     再输入n个k[i]   每个h[i]*2   可以用一个或多个k[i]相加得到(也可以是多个自身相加)

问这n个h[i]*2    最少需要多少个k[i]相加得到

比如样例:1 2 3 4  乘2 为 2 4 6 8

2=1+1  最少2个

4=4  最少1个

6=3+3=1+5   最少2个

8=5+3=4+4   最少2个

因此答案是7



思路 :   背包   把数作为背包的体积   对应的背包的值,这里为1 因为要求最小的个数吗 1就是1个 数


注意 千万注意    只要把体积设置为最大 调用一次即可 千万不要对每个h[i]都进行调用  千万注意  再这里吃了很多亏了啊



#include<stdio.h>
#include<string.h>
struct haha
{
	int val;
	int vol;
}k[505];
int n;
int bag[1005];
void _bag()
{
    int i,j,v=1000;
	for(i=1;i<=v;i++)
		bag[i]=999999999;
	bag[0]=0;
    for(i=0;i<n;i++)
    {
        for(j=k[i].vol;j<=v;j++)
        {
            bag[j]=(bag[j-k[i].vol]+k[i].val)<bag[j]?(bag[j-k[i].vol]+k[i].val):bag[j];
        }
    }
}
int main()
{
	int cas,i,j,h[505];
	int rem[1005];
	int num;
	scanf("%d",&cas);
	while(cas--)
	{
		memset(rem,0,sizeof(rem));
        scanf("%d",&n);
		for(i=0;i<n;i++)
		{
			scanf("%d",&num);
			rem[num*2]++;
		}
		for(i=0;i<n;i++)
		{
			scanf("%d",&k[i].vol);
			k[i].val=1;
		}
		int ans=0;
		_bag();//只要调用一次  注意
		   for(i=0;i<=1000;i+=2)
			if(rem[i])
			{
			    ans+=bag[i]*rem[i];
			}
			printf("%d\n",ans);
	}
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值