POJ-1260 Pearls---DP
题目链接:
https://cn.vjudge.net/problem/POJ-1260
题目大意:
给定一系列的不同质量项链上的珠宝数量和价格(按质量升序给出,同时价格也升序)。可以用价格高的珠宝来替代价格低的珠宝。这样或许可以节省总钱数。而题目就是要求出购买所有数量的珠宝所需支付的最低价格。
解题思路:
例如样例Input的第二个例子:
3
1 10
1 11
100 12
需要买第一类1个,第二类1个,第三类100个
按常规支付为 (1+10)*10 + (1+10)*11 + (100+10)*12 = 1551元(一共买了102个珍珠)
但是如果全部都按照第三类珍珠的价格支付,同样是买102个,而且其中总体质量还被提高了,但是价格却下降了:(102+10)*12 = 1344元
本题关键点在于:
(1) 要求要买的珍珠的数量是一定的
(2) 所买的珍珠的质量允许提高,但不允许下降(即可以用高质量珍珠替代低质量)
(3) 输入时,后输入的珍珠价格一定比前面输入的要贵
(4) 由(2)(3)知,珍珠的替代必须是连续的,不能跳跃替代(这个不难证明,因为假如用第i+2类去替代第i类珍珠,会使最终的支付价格降低,那么用第i+1类去替代第i类珍珠会使最终的支付价格更加低)
根据这4个约束条件,那么购买珍珠的方案为:
在珍珠类型的总区间[1,c]中划分多个子区间,其中在闭区间i1~j1的珍珠全部按第j1类珍珠的价格p1支付,在闭区间i2~j2的珍珠全部按第j2类珍珠的价格p2支付,…在闭区间in~jn的珍珠全部按第jn类珍珠的价格pn支付。 这些区间互不相交。
其余珍珠按其原价支付。
要求找出最优的划分方案,使得最终支付价格最低。
令dp[i]表示在已知第i类珍珠时,所需支付的最低价格
则状态方程为:
dp[i]=(a[i]+10)*p[i]+dp[i-1]; //当第i种珍珠出现时,未优化价格的情况
dp[i]=min(dp[i],(sum[i]-sum[j]+10)*p[i]+dp[j]); //枚举j,价格优化
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 #include<stack> 8 #include<map> 9 #include<sstream> 10 #define Mem(a, b) memset(a, b, sizeof(a)) 11 using namespace std; 12 typedef long long ll; 13 int dp[1005], sum[1005];//dp[i]表示前i个的最低价格,sum[i]表示前i个的数目 14 int a[1005], p[1005];//输入的数据,分别是个数和价格 15 int main() 16 { 17 int T, n; 18 cin >> T; 19 while(T--) 20 { 21 Mem(a, 0); 22 Mem(p, 0); 23 Mem(dp, 0); 24 Mem(sum, 0); 25 cin >> n; 26 for(int i = 1; i <= n; i++)cin >> a[i] >> p[i], sum[i] = sum[i - 1] + a[i]; 27 for(int i = 1; i <= n; i++) 28 { 29 dp[i] = dp[i - 1] + p[i] * (a[i] + 10); 30 for(int j = 0; j < i; j++) 31 dp[i] = min(dp[i], dp[j] + (sum[i] - sum[j] + 10) * p[i]);//只能有高价格代替低价格 32 } 33 cout<<dp[n]<<endl; 34 } 35 return 0; 36 }