要买若干种价值的珍珠,但买某种珍珠必须多付10颗此种珍珠的价钱,及如果买价值为1的珍珠100颗,必须付的钱数为110。一颗珍珠可以用比它贵的珍珠 充数,因此买多种珍珠的时候用贵的代替便宜的可能更省钱。
例一:
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元
例二:
2
100 1
100 2
一般情况下(100+10)*1 + (100+10)*2 =330元
但是全部都购买第二类珍珠,同样买200个,虽然总体质量提升了,但是价格也提高了: (202+10)*2=424元
1 /*首先是O(n^3)的方法,类似于矩阵连乘*/ 2 #include <iostream> 3 #include <cstdio> 4 #include <string.h> 5 using namespace std; 6 int main(){ 7 int t,n,a[105],p[105],sum[105],dp[105][105]; 8 scanf("%d",&t); 9 while(t--){ 10 scanf("%d",&n); 11 sum[0]=0; 12 for(int i=1;i<=n;i++){ 13 scanf("%d%d",a+i,p+i); 14 sum[i]=sum[i-1]+a[i]; 15 16 } 17 for(int j=1;j<=n;j++){ 18 for(int i=j;i>=1;i--){ 19 if(j==i)dp[i][i]=(a[i]+10)*p[i]; 20 else{ 21 dp[i][j]=(sum[j]-sum[i-1]+10)*p[j]; 22 for(int k=i;k<j;k++){ 23 dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]); 24 } 25 } 26 } 27 } 28 printf("%d ",dp[1][n]); 29 } 30 }
1 /*然后是O(n)的方法*/ 2 #include <iostream> 3 #include <cstdio> 4 #include <string.h> 5 using namespace std; 6 int main(){ 7 int t,n,a[105],p[105],sum[105],dp[105]; 8 scanf("%d",&t); 9 while(t--){ 10 scanf("%d",&n); 11 sum[0]=0; 12 for(int i=1;i<=n;i++){ 13 scanf("%d%d",a+i,p+i); 14 sum[i]=sum[i-1]+a[i]; 15 16 } 17 dp[0]=0; 18 for(int i=1;i<=n;i++){ 19 dp[i]=(a[i]+10)*p[i]+dp[i-1]; 20 for(int j=0;j<i;j++){ 21 dp[i]=min(dp[i],(sum[i]-sum[j]+10)*p[i]+dp[j]);//寻找最好的分割点 22 } 23 } 24 printf("%d ",dp[n]); 25 } 26 }