POJ 1260 Pearls

博客讨论了一道关于优化珍珠采购的动态规划问题。题目要求在满足需求和避免单一珍珠购买的情况下,计算最小采购成本。博主指出,最优解中不会存在交叉替换,并提供了证明。最后,博主给出了使用动态规划求解的代码实现。

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

传送门:Pearls
在这里插入图片描述
在这里插入图片描述
题意:有c种不同品质的珍珠,分别给出各种珍珠的需求数目num和单价price,对于采购人员来说,要购买足够多数量的各种珍珠,但每种珍珠可以购买或者是要求的种类,或者是品质更好的珍珠。同时,为了避免有人只买一个珍珠,所以无论购买完成哪一种珍珠,都要交付10*price的额外成交价。
  输入时以珍珠的递增价格输入。
  要求计算购买足够的珍珠(可以以要求的品质购买,也可以选一些品质更高的珍珠)所需要的最小金钱。
思路:这道题的意思有点难理解,写的时候我都不知道为啥可以以同一个价格来买。。。一开始我就两种情况取最小值,一种全部用自己的价格来买,另一种全都用最大的价格来买,嗯,理所应当的wa了:)。

其实这道题的正确思路是:定义dp[i]:代表采购前i种珍珠所需要花费的最小价格,当要采购第i+1种时,有两种情况,一种是只有第i+1种取第i+1个价格,那么dp[i+1]=dp[i]+(num[i+1]-num[i]+10)*p[i+1];另一种是第j种珍珠到第i+1种珍珠都取第i+1个价格,那么dp[i+1]=dp[j]+(num[i+1]-num[j]+10)*p[i+1]);这两种情况取最小值即可。

那么就有一个问题了,为啥不能交叉替换价格呢?这个一开始我也没想通,看了某个博客才知道的,以下为粗略的证明过程:

首先证明最优解中肯定不会有交叉的替换,即在质量为a<b<j<c<d的情况下,如果a被c替换,那么b也一定要被c替换 假设在最优解中存在:a被c替换且b不被c替换的情况:

1.b不被任何替换 那么此时把a换成用b替换 得到比原来更优的解,错误
2.b被j替换,此时把a换成用j替换 得到比原来更优的解,错误
3.b被d替换,此时把b换成用c替换 得到比原来更优的解,错误

因此,不存在交叉替换。
代码

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int num[105],p[105],t,dp[105];
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		int c;
		scanf("%d",&c);
		for(int i=1;i<=c;i++)
		{
			scanf("%d%d",&num[i],&p[i]);
			num[i]=num[i-1]+num[i];
		}
		memset(dp,0,sizeof(dp));
		for(int i=0;i<c;i++)
		{
			dp[i+1]=dp[i]+(num[i+1]-num[i]+10)*p[i+1];
			for(int j=0;j<i;j++)
			{
				dp[i+1]=min(dp[i+1],dp[j]+(num[i+1]-num[j]+10)*p[i+1]);
			}
		}
		printf("%d\n",dp[c]);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值