每日随机一题 leetcode1449. 数为成本和为目标值的最大数字 完全背包问题,两个小时 自己写出来了!

题:
在这里插入图片描述


思:
最终的数位成本和必须恰好等于target
换算为背包问题(拿了以后还可以再拿)
数位1到9 对应9个物品,cost[0到8] 对应9个物品的重量;物品本身代表了自己的价值:
要在尽可能的多拿物品(多拿数位),然后对结果进行排序,得到最大的价值
所以可以把每个物品的价值都理解为1,因为每个物品的价值是等价的
dp[i]表示重量为i的时候,最大的数位和(String类型)
对于每一个物品(数位),我们可以选择拿或者不拿,如果拿的话,则把它插入到头部,因为循环越往后,数位越大,这样就无需给已经获得的数位排序了
每一个物品的重量(cost)为c,价值为1,因此数位和的长度直接代表了价值,无需在dp里存放价值
每一个物品(数位)的值恰好为循环的次数k
因此dp[i] = max(dp[i],“k”+dp[i-c]) 如果dp[i-c]为0(字符串里是"“代表空),则"k”+dp[i-c]也为"" ,当二者长度相同时(这里是为了满足恰好等于target)
如果二者长度不同,则dp[i] = 二者中长度长的那个
不用避免过去的自己被先更新,且同一个数位可以重复使用多次,因此内部循环应该从小往大遍历
最重要的一点:一个数字可以重复多次被拿,所以dp[i-c]应该循环数次,从小往大遍历可以直接解决这个问题(骚操作!)


码:

public static String largestNumber(int[] cost, int target) {
        String[] dp = new String[target + 1];
        for (int i = 0; i < dp.length; i++) {
            dp[i]="";
        }
        // 固定cost的大小为9
        for (int a = 1; a <= 9; a++) {
            int c = cost[a - 1]; // 第a个数位的成本为cost[a-1]
            // 如果当前数位的成本大于target,就别考虑它了
            if(c > target){
                continue;
            }
            String k = "" + a; // 每一个物品(数位)的值恰好为循环的次数k
            // 每次应该先对当前物品,确定一下重量为多少的时候,可以拿它。
            if (dp[c].length() == 0) {
                dp[c] = k;
            }else if(dp[c].length() == 1){
                dp[c] = dp[c].compareTo(k)>0?dp[c]:k;
            }

            for (int i = c; i <= target; i++) {
                if (dp[i - c] == "") {
                    dp[i] = dp[i];
                } else {

                    if (dp[i].length() == (k + dp[i - c]).length()) {
                        // 比较字符串
                        if (dp[i].compareTo(k + dp[i - c]) < 0) {
                            dp[i] = k + dp[i - c];
                        }

                    } else if (dp[i].length() > (k + dp[i - c]).length()) {
                        dp[i] = dp[i];
                    } else {
                        dp[i] = k + dp[i - c];
                    }
                }
            }
        }
        if(dp[target]=="")
            return "0";
        return dp[target];
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值