首页 > 代码库 > poj 1260 Pearls ( 区间dp )

poj 1260 Pearls ( 区间dp )

链接:poj 1260

题意:给出n类珍珠,所需它们的数量,以及它们的单价,

要求用最少的钱就可以买到相同数量的,相同(或更高)质量的珍珠。

注:价格更高的珍珠等级更高,支付规则为:

买任一类的珍珠n个(单价:p),都要支付(n+10)*p的钱

例如:

3

1 10

1 11

100 12

需要买第一类1个,第二类1个,第三类100个

按常规支付为 (1+10)*10 + (1+10)*11 + (100+10)*12 = 1551元

但是如果全部都按照第三类珍珠的价格支付,同样是买102个,

而且其中总体质量还被提高了,但是价格却为:(102+10)*12 = 1344元下降了

分析珍珠的替代必须是连续的,不能跳跃替代

因为如果用第i+2类去替代第i类珍珠,会使最终的支付价格降低,

那么用第i+1类去替代第i类珍珠会使最终的支付价格更加低

在珍珠类型的总区间[1,n]中划分多个子区间,

在闭区间in-jn的珍珠全部按第jn类珍珠的价格pn支付。

这些区间互不相交。其余珍珠按其原价支付。

要求找出最优的划分方案,使得最终支付价格最低。

 

令dp[i]表示在已知第i类珍珠时,所需支付的最低价格

状态方程为:

dp[i]=(a[i]+10)*p[i]+dp[i-1];  //当第i种珍珠出现时,按常规支付第i类的价格

dp[i]=min(dp[i],(s[i]-s[j]+10)*p[i]+dp[j]);  //枚举j,价格优化

s[i]为需要第1类珍珠到第i类珍珠的总个数


#include<stdio.h>
#define min(a,b) a<b?a:b
int main()
{
    int T,n,i,j,a[105],p[105],s[105],dp[105];
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        s[0]=0;
        for(i=1;i<=n;i++){
            scanf("%d%d",&a[i],&p[i]);
            s[i]=s[i-1]+a[i];
        }
        dp[0]=0;
        for(i=1;i<=n;i++){
            dp[i]=dp[i-1]+(a[i]+10)*p[i];
            for(j=0;j<i;j++)
                dp[i]=min(dp[i],dp[j]+(s[i]-s[j]+10)*p[i]);
        }
        printf("%d\n",dp[n]);
    }
    return 0;
}



poj 1260 Pearls ( 区间dp )