9.7去哪儿笔试-01背包问题

《重启21》

9.7——去哪儿笔试-01背包问题

前言

博主又又又n次参加秋招笔试了,这次所属有点打脸,让博主这种想速成算法的人感觉到了绝望。。。笔试一共3到算法题,前两道对于经常算题的人来说是频见题,不过对于博主这种就没怎么算明白了。。。其中一个01背包问题,博主很久就听说过了,但做的少没有出现过相应题目,又没去了解。昨天就翻大车了。。。

题目

大意:冬奥会的体操比赛,有i个动作,每个动作有对应的体力消耗n和得分m,然后运动员有体力t。如果运动员要尽量高的成绩要怎么做动作?

假设:运动员不做重复的动作,i>0,n>0,m>0,0<=t

输入:
10 [[1,1],[2,3],[3,5],[5,10],[6,8],[7,9],[9,10]]
18

ps:第一排的10代表t,二维数组为动作和得分,如[5,10]5为体力消耗,10为得分数
第二排为运动员的得分

要求:<2ms

代码

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 运动员可得到的最高分
     * @param t int整型 运动员体力值
     * @param actions int整型二维数组 二维数组i为动作号 actions[i][0]为动作i+1消耗体力,actions[i][1]为动作i+1得分
     * @return int整型
     */
    public  int maxScore(int t,int[][] actions){
        int len=actions.length+1; //多少个动作+1(因为我要加入0号动作消耗0获取0分)
        int[] acts = new int[len]; // 每个动作对应的体力
        int[] score = new int[len]; // 每个动作对应的价值
        acts[0]=0;
        for (int i=1;i<len;i++){
            acts[i]=actions[i-1][0];
        }
        score[0]=0;
        for (int i=1;i<len;i++){
            score[i]=actions[i-1][1];
        }

        int[][] v=new int[len][t+1];
        for(int i=0;i<len;i++){
            for(int j=0;j<t+1;j++){
                if(i==0){
                    v[i][j]=0; // 边界情况:V(0,j)=0
                }else if(j==0){
                    v[i][j]=0; // 边界情况:V(0,j)=0
                }else{
                    if(j<acts[i]){
                        v[i][j]=v[i-1][j]; // 包的容量比当前该物品体积小,装不下,此时的价值与前i-1个的价值是一样的,即V(i,j)=V(i-1,j);
                    }else {
                        v[i][j]=Math.max(v[i - 1][j], v[i - 1][j - acts[i]] + score[i]);// 还有足够的容量可以装当前该物品,但装了当前物品也不一定达到当前最优价值,所以在装与不装之间选择最优的一个,即V(i,j)=max{V[i-1,j],V[i-1,j-acts(i)]+score[i]}。
                    }
                }
            }
        }
        return v[len-1][t];
    }
//        int[] item=new int[len];
//        Arrays.fill(item,0);
//
//        // 从最优解,倒推回去找
//        int j = t;
//        for (int i = len-1; i > 0; i--) {
//            if (v[i][j] > v[i - 1][j]) {// 在最优解中,v[i][j]>v[i-1][j]说明选择了第i个商品
//                item[i] = 1;
//                j = j - acts[i];
//            }
//        }
//
//        System.out.print("包内物品的编号为:");
//        for (int i = 0; i < len; i++) {
//            if (item[i] == 1) {
//                System.out.print(i + " ");
//            }
//        }
//        System.out.println("----------------------------");

}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值