Loading

考研机试 66.点菜问题

 

时间:2021/03/09

 

一.题目描述

北大网络实验室经常有活动需要叫外卖,但是每次叫外卖的报销经费的总额最大为C元,有N种菜可以点,经过长时间的点菜,网络实验室对于每种菜i都有一个量化的评价分数(表示这个菜可口程度),为Vi,每种菜的价格为Pi, 问如何选择各种菜,使得在报销额度范围内能使点到的菜的总评价分数最大。     注意:由于需要营养多样化,每种菜只能点一次。

输入描述

输入的第一行有两个整数C(1 <= C <= 1000)和N(1 <= N <= 100),C代表总共能够报销的额度,N>代表能点菜的数目。
接下来的N行每行包括两个在1到100之间(包括1和100)的的整数,分别表示菜的>价格和菜的评价分数

输出描述

输出只包括一行,这一行只包含一个整数,表示在报销额度范围内,所点的菜得到的最大评价分数。

题目链接

https://www.nowcoder.com/practice/b44f5be34a9143aa84c478d79401e22a?

tpId=40&tqId=21397&rp=1&ru=%2Fta%2Fkaoyan&qru=%2Fta%2Fkaoyan%2Fquestion-ranking&tab=answerKey

 

二.算法

题解

本题是在求给定金额下的最优值问题,由于每种菜只能购买一次,所以这是一个典型的0-1背包问题,也就是一个选与不选的问题。对于0-1背包问题的求解思路:若背包的最大容量记为c,物品有n种,每种物品都有自己的重量和价值,则我们建立一个n+1行,c+1列的数组dp,建立完数组后,我们令第零行和第零列的值为0,然后开始从第一行、第一列遍历整个dp数组,若当前容量j(也就是列数)大于等于该行所代表物体的重量,则dp[i][j]=max(dp[i-1][j],dp[i-1][j-该行多代表物体的重量] + 该行所代表物体的价值),即取选与不选中较大的那一个;若当前容量小于该行所代表物体的重量,则dp[i][j]=dp[i-1][j]。一定要注意下标,最好都从1开始。 

重点

0-1背包问题

代码

import java.util.Scanner;

public class Main{
    
    public static void main(String[] args){
        //读取输入
        Scanner in = new Scanner(System.in);
        while(in.hasNext()){
            int c = in.nextInt();
            int n = in.nextInt();
            int[] p = new int[n];
            int[] v = new int[n];
            for(int i = 0; i < n; i++){
                p[i] = in.nextInt();
                v[i] = in.nextInt();
            }
            //求解点菜问题(根据0-1背包问题的思路)
            int[][] dp = new int[n + 1][c + 1];
            for(int i = 0; i <= c; i++){
                dp[0][i] = 0;
            }
            for(int i = 0; i <= n; i++){
                dp[i][0] = 0;
            }
            for(int i = 1; i <= n; i++){
                for(int j = 1; j <= c; j++){
                    if(j >= p[i - 1]){
                        dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - p[i - 1]] + v[i - 1]);
                    }else{
                        dp[i][j] = dp[i - 1][j];
                    }
                }
            }
            System.out.println(dp[n][c]);
        }
        //System.out.println(dp(0, n - 1));
    }
    
    //使用递归求解动态规划问题
//     public static int dp(int money, int index){
//         if(money > c){
//             return 0;
//         }
//         if(index < 0){
//             return 0;
//         }else{
//             return Math.max(dp(money, index - 1), dp(money + p[index], index - 1) + v[index]);
//         }
//     }
}

 

posted @ 2021-03-09 15:14    阅读(116)  评论(0编辑  收藏  举报