大疆19年校招0806笔试B卷第一题(背包问题)

同学晚上做题,我就看了看第一题,这个第一题有点像四号的第二题,但是由于游戏时间必须全部完成才能得到满意度,所以选择游戏的时候只依靠贪心算法不够了,需要用动态规划来解决问题。

题目:游戏王

小明要玩游戏,每个游戏都有它的成就值,也有玩这个游戏需要花费的时间(每个游戏必须玩完才能获得成就值)。小明总共有T的时间。求在T的时间内可以获得的最大成就值。

输入:
第一行输入case数T(0<T<20)。对于每个case,第一行输入游戏的数目N(0<N<11),总时间X(0<X<1000)用空格分割。从第二行到第N+1行每行输入游戏的成就值Ai(0<Ai<10000),所需要花费时间Bi(0<Bi<10000)。

输出:
对于每个case输出一行,成就值之和的最大值。

样例输入:
2
2 2
10 1
20 2
3 4
10 2
18 3
10 2

样例输出:
20
20

题目分析

典型的01背包问题

基本思路是将该问题转化为子问题进行求解。考虑N件物品在限重M的背包下可选择的最大价值F[N][M],这个问题可以分解成两种情况来考虑:这是一个非黑即白的问题,因为一个物品只存在两种状态,放入背包和没有放入背包.

  • N1不放入背包,则问题转化为F[N-1][M],N1不放入背包,则物品数减一
  • N1放入背包,问题转化为value[N1]+f[N-1][M-weight[N1]],N1放入背包,则背包承重减少。

原问题的解取上面两种情况中的最大值。既F[N][M] = max{F[N-1][M], (F[N-1][M-weight[N1]+value[N1]))}。接下来问题又变成了求解F[N-1][M]F[N-1][M-weight[N1]两个子问题。然后一直类推到一个物品时。以此类推的话我们解决原始问题需要子问题的解。我们需要先计算子问题,自底向上求解。解决顺序如下表。从左到右,从上到下计算。货品的顺序不影响最后的计算结果。
采用二维数组存贮状态值,自下而上避免重复计算。更详细的可以参考01背包问题——贪心+DP

代码实现

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {

        Scanner in = new Scanner(System.in);
        int T = in.nextInt();
        while (T-- > 0) {
            int gamenum = in.nextInt();
            int havedays = in.nextInt();
            int value[] = new int[gamenum + 1];
            int days[] = new int[gamenum + 1];
            int allvalue = 0;
            int alldays = 0;
            for (int i = 1; i <= gamenum; i++) {
                value[i] = in.nextInt();
                days[i] = in.nextInt();
                allvalue += value[i];
                alldays += days[i];
            }
            if (alldays <= havedays)
                System.out.println(allvalue);
            else {
                int dp[][] = new int[gamenum + 1][havedays + 1];
                for (int i = 0; i <= havedays; i++) {
                    dp[0][i] = 0;
                }
                for (int i = 0; i <= gamenum; i++) {
                    dp[i][0] = 0;
                }
                for (int i = 1; i <= gamenum; i++) {
                    for (int j = 1; j <= havedays; j++) {
                        if (j < days[i]) {
                            //当背包的重量小于当前物品的重点时,则沿用上一行的value值
                            dp[i][j] = dp[i - 1][j];
                        } else {
                            dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - days[i]] + value[i]);
                        }
                    }
                }
                System.out.println(dp[gamenum][havedays]);
            }
        }
    }
}
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值