华为机试:购物单(考点:动态规划)

题目:


分析:这是一道01背包问题,有一个限制条件就是附件必须要在主件购买的前提下才能购买。本题的总钱数就类似于背包问题中的总重量,价格与重要度乘积的总和就类似于背包问题中的价值。定义数组dp[i][j]表示前i件物品花费j所得到的最大价值,对于每件物品可以选择放或者不放,具体:

(1)如果j<price[i-1](第i件物品的价格),则不能放入,dp[i][j]=dp[i-1][j];

(2)如果j>=price[i-1],那么可以选择放或者不放,分别对于转移方程:dp[i][j]=dp[i-1][j-price[i-1]]+v[i],dp[i][j]=dp[i-1][j];取两者中较大值,即

dp[i][j]=max{dp[i-1][j-price[i-1]]+v[i],dp[i][j]=dp[i-1][j]}。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
            int N = scanner.nextInt();
            int m= scanner.nextInt();
            int[] price=new int[m];
            int[] value=new int[m];
            int[] ZhuFu=new int[m];
            for(int i=0;i<m;i++){
                price[i]=scanner.nextInt();
                value[i]=scanner.nextInt()*price[i];   //定义 价值=重要度*价格
                ZhuFu[i]=scanner.nextInt();
            }
            //采用动态规划
            int[][] dp=new int[m+1][N+1];  //dp[i][j]表示用j钱购买i件物品的总价值
            for(int i=1;i<=m;i++){
                for(int j=1;j<=N;j++){
                    if(ZhuFu[i-1]==0){  //表示为主件
                        if(j>=price[i-1]){
                            dp[i][j]=Math.max(dp[i-1][j],dp[i-1][j-price[i-1]]+value[i-1]);    //分别表示不买第i件和买第i件物品之后的最大价值
                        }else{
                            dp[i][j]=dp[i-1][j];
                        }
                    }else{    //表示为附件,附件需要购买主件
                        if(price[i-1]+price[ZhuFu[i-1]-1]<=j){
                            dp[i][j]=Math.max(dp[i-1][j],dp[i-1][j-price[i-1]-price[ZhuFu[i-1]-1]]+value[i-1]);
                        }else{
                            dp[i][j]=dp[i-1][j];
                        }
                    }
                }
            }
            System.out.println(dp[m][N]);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_27139155/article/details/79767539
今日推荐