題意:給出幾類珍珠,以及它們的單價,要求用最少的錢就可以買到相同數量的,相同(或更高)質量的珍珠。
例如樣例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;
}