poj-1260 Pearls

題意:給出幾類珍珠,以及它們的單價,要求用最少的錢就可以買到相同數量的,相同(或更高)質量的珍珠。

例如樣例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

 

而對於樣例Input的第一個例子:

2

100 1

100 2

按常規支付爲(100+10*1 + (100+10)*2 =330

但是全部按第二類珍珠的價格支付,同樣買200個,雖然總體質量提升了,但是價格也提高了: (202+10)*2=424

 根據數據的分析可知,我們需要在總體質量提升的同時使價格不提升。也就是以一個較少的錢來買多數珍珠。開始我們需要累加每一次購買珍珠的數量 sum[i] = sum[i-1]+a[i];

在默認情況下每個狀態的dp都是單獨付錢的,然而這樣並不會是最優情況,所以我們根據sum數組找到所有與之前的珍珠合爲一組的情況,然後與當前狀態比較找到最小前數。

dp[i]=min(dp[j]+(sum[i]-sum[j]+10)*p[i],dp[i]); 這是這一步的狀態轉移方程。

以下爲代碼

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;

int dp[1400];
int a[1100];
int p[1100];
int sum[1100];
int main()
{
    int t,n;
    int i,j;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        sum[0]=0;
        dp[0]=0;
        for(i=1;i<=n;i++)
        {
            scanf("%d%d",&a[i],&p[i]);
            sum[i] = sum[i-1]+a[i];
        }
        for(i=1;i<=n;i++)
        {
            dp[i]=(a[i]+10)*p[i]+dp[i-1];
            for(j=i-1;j>=0;j--)
            {
                dp[i]=min(dp[j]+(sum[i]-sum[j]+10)*p[i],dp[i]);
            }
        }
        printf("%d\n",dp[n]);
    }
    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章