输入字符串的背包解决方案

Posted

技术标签:

【中文标题】输入字符串的背包解决方案【英文标题】:Knapsack solution for input of strings 【发布时间】:2018-07-21 13:20:54 【问题描述】:

我进行了在线编码测试,问题描述如下。我无法完成这个问题,但确实留下了一些关于如何提出潜在解决方案的问题。我想知道解决这个问题的最佳方法是什么。我遇到的主要问题是将给定的输入拆分为字符串并找到合适的集合来放入它们。下面是问题。

你想给你的朋友寄一个包含不同东西的包裹。 您放入包裹中的每件物品都有索引号、重量和成本等参数。

包裹有重量限制。 您的目标是确定要放入包裹中的物品,以使总重量小于或等于包裹限制,并且总成本尽可能大。

如果有多个相同价格的包裹,您希望发送重量较轻的包裹。 这是背包问题的变体。

输入: 您的程序应该从标准输入中读取行。每行包含一个包裹可以承受的重量(在冒号之前)以及您需要从中挑选的东西的列表。每个事物都用括号括起来,其中第一个数字是事物的索引号,第二个是它的重量,第三个是它的成本。 任何包裹的最大重量为<= 100. 您可能需要选择多达 15 项内容。 任何东西的最大重量和最大成本是<= 100.

输出: 为每组事物生成您放入包中的事物列表(它们的索引号以逗号分隔)。如果包装中没有任何物品,请打印连字符(-).

测试 1 输入81 : (1,53.38,$45) (2,88.62,$98) (3,78.48,$3) (4,72.30,$76) (5,30.18,$9) (6,46.34,$48)

预期输出4

测试 2

Test Input 75 : (1,85.31,$29) (2,14.55,$74) (3,3.98,$16) (4,26.24,$55) (5,63.69,$52) (6,76.25,$75) (7,60.02,$74) (8,93.18,$35) (9,89.95,$78)

预期输出2,7

【问题讨论】:

这可以通过多种方式解决。我给出了一种解决方案。它的子集问题之和。也可以使用动态规划来解决 【参考方案1】:

您可能需要选择多达 15 项内容。所以你有可能的组合 2^15 = 32,768。这样你就可以 检查每个组合,找出符合要求的组合。

示例:有 3 (1,2,3) 个事物。 那么你可以选择:(),(1),(2),(3),(1,2),(1,3),(2,3),(1,2,3)。 现在需要找出符合要求的组合。

这里是解决方案:

 public static void main(String[] args) 
    Scanner in = new Scanner(System.in);
    String s = in.nextLine();
    String res[] = s.replaceAll("[^0-9.]+",";").split(";");
    double target = Integer.parseInt(res[0]);
    int n = (res.length-1) / 3;
    int[] Index = new int[20];
    double[] P = new double[20];
    double[] W = new double[20];
    int jj = 0;
    for(int i = 1; i < res.length; i +=3)
        Index[jj] = Integer.parseInt(res[i]);
        W[jj] = Double.parseDouble(res[i+1]);
        P[jj++] = Double.parseDouble(res[i+2]);
    
    double result = 0;
    int track = 0;
    double resSum = 0;
    for(int i =0; i< (1<<n); i++)
        double sum = 0;
        double weight = 0;
        for(int j=0; j < n; j++)
            if(((1<<j)&i) > 0)
                sum+= P[j];
                weight+=W[j];
            
        
        if(weight <= target)
            if(sum > resSum)
                result = weight;
                track = i;
                resSum = sum;
            else if(sum == resSum && weight < result)
                result = weight;
                track = i;
            
        
    
    jj = 0;
    for(int i = 0; i < n; i++)
        if(((1<<i)&track) > 0)
           if(jj > 0)
               System.out.print(",");
           
           jj = 1;
           System.out.print(Index[i]);
        
    
    if(track == 0)
        System.out.println("-");
    else 
        System.out.println();
    

【讨论】:

以上是关于输入字符串的背包解决方案的主要内容,如果未能解决你的问题,请参考以下文章

c++ - 如何在递归中使用记忆来解决0-1背包问题而没有运行时错误以在c ++中进行较大的输入?

518-零钱兑换 II(完全背包-求方案总数)

背包九讲之九:背包问题求具体方案

请帮助我解决分数背包问题(战利品的最大值)

我的背包有问题吗

acwing 012 背包问题求具体方案