涉及算法:动态规划(dp)
题目大意:给定n种不同种类的珍珠,每种珍珠对应着一个单价和一个购买量,要求我们以最少的钱买到同样总量珍珠,而且保证珍珠的品质不能下降,任意购买一种价格为p数量为n的珍珠需要支付:(n+10)*p
题目分析:
我们以dp[i]表示只考虑购买第1到第i种珍珠所花费的最少的钱,amt[i]表示需要购买的第i种珍珠数,sum(i,j)表示第i到第j种珍珠的总数,p[i]表示第i种珍珠的数目
这里有一点需要说明:替代必须是连续的,即若k用i替换,则k+1到i-1也要用i替换,我们来证明下,如果i-2用i替换而i-1保持不变所花费的钱一定大于i-2用i-1替换所花费的钱。
那么对于dp[i+1]可以分为如下几种情况,我们只需要取其中的最小值即可
1、第i+1种不替代任何珍珠
2、第i+1种替代第i-1种珍珠
3、第i+1种替代第i-2--i-1
4、第i+1种替代第i-3--i-1
。。。
一直到第i+1替代第1--i-1
公式如下:
dp[i+1]=min{dp[k]+(amt[i+1]+10+sum(k+1,i))*p[i+1]} 0<=k<=i
有以下几点需要注意:
1、珍珠的品质(价格)是向后依次升高
2、品质不能下降即不能以低品质珍珠代替高品质珍珠
3、总购买量是一定的而每种珍珠的购买量可以重新分配
4、若珍珠k用i来替换则k+1到i-1也要用i来替换
import java.util.Arrays;
import java.util.Scanner;
public class Main_1260 {
static int n;
static int[] amt;
static int[] p;
static int[] dp=new int[101];
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
int m=in.nextInt();
while(m-->0){
n=in.nextInt();
amt=new int[n+1];
p=new int[n+1];
for(int i=1;i<=n;i++){
amt[i]=in.nextInt();
p[i]=in.nextInt();
}
dp();
System.out.println(dp[n]);
}
}
static void dp(){
Arrays.fill(dp, 0);
dp[0]=0;
for(int i=1;i<=n;i++){
dp[i]=dp[i-1]+(amt[i]+10)*p[i];
int sum=0;
for(int j=i-1;j>=1;j--){//把j到i-1用i来代替
sum+=amt[j];
if(dp[i]>dp[j-1]+(amt[i]+10+sum)*p[i]){
dp[i]=dp[j-1]+(amt[i]+10+sum)*p[i];
}
}
}
}
}