POJ1260

要买若干种价值的珍珠,但买某种珍珠必须多付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\n",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\n",dp[n]);
25     }
26 }

 

posted @ 2015-03-08 22:20  Mr.XuJH  阅读(138)  评论(0编辑  收藏  举报