传送门: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;
}