【问题标题】:Recursive Knapsack递归背包
【发布时间】:2014-05-03 07:01:23
【问题描述】:

我正在尝试实现递归背包我使用通用算法编写如下:

int pack(int n, int s) {
    if (n < 0)
        return 0;
    if (List[n].s > s)
        return pack(n-1, s);
    else {
        int max =  Math.max(pack(n-1,s), pack(n-1, s -List[n].s) + List[n].v);
        return max;
    }
}

无论如何我可以知道哪些物品被包装了吗?

更新:我只想要属于最佳选择的项目,我不想更改函数标题。

EDIT使用数组来追踪物品,这有什么问题?

int pack(int n , int s)
{
     if(n < 0)
     {
         counter =0;
         return 0;
     }
     if (itemsList[n].s > s)
     {
        return pack(n-1, s);
     }
     else
     {
         int max1 = pack(n-1,s);
         int max2 = pack(n-1, s - itemsList[n].s) + itemsList[n].v ;

        if(max2 > max1)
        {
            flag1[counter] = new item();
            flag1[counter] = itemsList[n];
            counter ++;
        }
         return max(max1, max2);
     }         
}

【问题讨论】:

  • 这将返回所有的试验,然后再找到最佳的物品选择,我只想要包装好的物品

标签: java knapsack-problem


【解决方案1】:

这样的?

int pack(int n, int s) {
    if (n < 0)
        return 0;
    if (List[n].s > s)
        return pack(n-1, s);
    else {
        int without = pack(n-1,s);
        int with = pack(n-1, s-List[n].s) + List[n].v;
        if (with >= without) {
            System.out.println(n);                
        }
        return Math.max(with, without);
    }
}

或者,您可以返回结果列表:

int pack(int n, int s) {
    return reallyPack(n, s, new ArrayList<Item>());
}

int reallyPack(int n, int s, List<Item> l) {
    if (n < 0)
        return 0;
    if (List[n].s > s)
        return reallyPack(n-1, s);
    else {
        int without = reallyPack(n-1,s);
        int with = reallyPack(n-1, s-List[n].s) + List[n].v;
        if (with >= without) {
            l.add(itemsList[n]);
        }
        return Math.max(with, without);
    }
}

当然,您仍然知道选择了多少项目:这只是返回列表的大小。

【讨论】:

  • 没有返回最佳选择,返回另一个!
  • 输入数据是什么,打印了什么?
  • 这是输入数据: 7 7 9 5 12 14 6 12 3 4 2 6 7 3 5 使用 7,9,6,12 和仅空格 15 的总和应为 34。结果是 6,12,5,12,值为 35,空格为 16!
  • 所以你提供了 V 数组,S 数组是什么?你用 s = 15 还是 16 调用 pack ?
  • 事实上我尝试打印并且它正在工作最后四个打印是 0,1,5,6 但我需要做的是将这些项目存储在一个数组中,所以我认为管理索引那个数组就是问题!
【解决方案2】:

您可以跟踪当前选择的所有项目(使用例如boolean[] 字段)。然后你必须记住 n &lt; 0 的调用中的最大值。

int maximum;
int currentMax;
boolean[] packed;
boolean[] maxPacked;

int pack(int n, int s) {
    if (n < 0) {
        if (maximum < currentMax) {
            // found better selection
            maximum = currentMax;
            // copy array
            for (int i = 0; i < packed.length; i++)
                 maxPacked[i] = packed[i];
        }
        return 0;
    }

    packed[n] = false;
    int maxWithout = pack(n-1, s);
    if (List[n].s > s) {
        return maxWithout;
    } else {
        packed[n] = true;
        currentMax += List[n].v;
        int maxWith = pack(n-1, s -List[n].s) + List[n].v;
        currentMax -= List[n].v;

        return Math.max(maxWith, maxWithout);
    }
}

void callingFunction() {
    int maxCost = //...;
    // always possible to choose no items
    maximum = 0;
    currentMax = 0;
    packed = new boolean[List.length];
    maxPacked = new boolean[List.length];

    pack(List.length-1, maxCost);
    // print best selection
    System.out.println(Arrays.toString(maxPacked));
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多