hdu1300 & poj1260 Pearls
题意:有n种珠宝,每件珠宝有必须要买的数量ai和单价pi,c种珠宝的单价递增。如果买了某种珠宝,需要额外付一次10*pi的费用(据说是为了防止你只买一件。。。),同时可以买同等数量单价高的珠宝代替单价低的珠宝,这样可能会省一些钱。求买完所需的珠宝需要的最少花费。
分析:
比如5……n的珠宝中,第6,7,9,11种珠宝被购买,称为A,其余是被替换的,称为B。
那么对于第4种珠宝,若选择购买B类珠宝,那么都没有选择自己优。若选择购买A类珠宝,那么选择第6种珠宝最优。原因是一样的,首先是价钱在同类中最低,而且对于1……3种珠宝的替换在同类中最有利。
可以发现,6,7,9,11 or 6,8,12,15,or 6…… 这些决策序列,对于第4种珠宝来说,都是一样的,最优决策只会在选自己和选第6种珠宝中产生。
我提取的状态就是:dp[i][j],表示前 i 种珠宝在 i 右端第一个A类珠宝是 j 时的最优值。
状态转移:dp[i][j]=min( (a[i]+10)*p[i]+dp[i-1][i] , a[i]*p[j]+dp[i-1][j] )
第n中珠宝只能选自己,那么目标状态就是dp[n-1][n]+(a[n]+10)*p[n]
View Code
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N = 105; 6 7 int dp[N][N],a[N],p[N]; 8 9 int solve(int s,int k) 10 { 11 if( dp[s][k]!=-1 ) return dp[s][k]; 12 return dp[s][k]=min( (a[s]+10)*p[s]+solve(s-1,s),a[s]*p[k]+solve(s-1,k) ); 13 } 14 15 int main() 16 { 17 int t,n; 18 19 scanf("%d",&t); 20 while( t-- ) 21 { 22 scanf("%d",&n); 23 for(int i=1;i<=n;i++) 24 scanf("%d%d",&a[i],&p[i]); 25 memset(dp+1,-1,n*sizeof(dp[0])); 26 printf("%d\n",solve(n-1,n)+(a[n]+10)*p[n]); 27 } 28 return 0; 29 }