很明显的,当vi<vj<vk且i可以用j来代替(即(si+10)*vi<si*vj)时,则当前解为最优解(因为si*vj<si*vk - -...)。
用dp[j]表示前j种pearl的最小代价,i>j&i=1...n,dp[1]=(s1+10)*v1,用第i种pearl替代前i-j种,得状态转移方程:
dp[i] = min(dp[j] + (sum[i]-sum[j]+10)*val[i]) ;
代码:
#include<cstdio>
int sum[1001], val[1001], dp[1001] ;
int main(){
int t, i, j, n, min ;
scanf("%d", &t) ;
while(t--){
scanf("%d", &n) ;
sum[0] = dp[0] = 0 ;
for(i=1; i<=n; i++){
scanf("%d%d", &j, &val[i]) ;
sum[i] = sum[i-1] + j ;
}
for(i=1; i<=n; i++){
min = 2147483647 ;
for(j=0; j<i; j++){
dp[i] = dp[j] + (sum[i]-sum[j]+10)*val[i] ;
if(dp[i]<min) min = dp[i] ;
}
dp[i] = min ;
}
printf("%d\n", dp[n]) ;
}
return 0 ;
int sum[1001], val[1001], dp[1001] ;
int main(){
int t, i, j, n, min ;
scanf("%d", &t) ;
while(t--){
scanf("%d", &n) ;
sum[0] = dp[0] = 0 ;
for(i=1; i<=n; i++){
scanf("%d%d", &j, &val[i]) ;
sum[i] = sum[i-1] + j ;
}
for(i=1; i<=n; i++){
min = 2147483647 ;
for(j=0; j<i; j++){
dp[i] = dp[j] + (sum[i]-sum[j]+10)*val[i] ;
if(dp[i]<min) min = dp[i] ;
}
dp[i] = min ;
}
printf("%d\n", dp[n]) ;
}
return 0 ;
}