英文:
Submission and custom input on GeeksForGeeks gives different judge result on same test case
问题
我使用了GeeksForGeeks上的一个问题分数背包问题进行练习:
给定N个物品的重量和价值,我们需要将这些物品放入一个容量为W的背包中,以获得背包中的最大总价值。
**注意:**与0/1背包不同,您可以拆分物品。
示例1:
输入:
N = 3,W = 50;
values[] = {60,100,120};
weight[] = {10,20,30};
输出:
240.00
解释:
我们可以从给定的背包容量中获得的物品的最大总价值为240.00。
当我提交我的代码时,在线评测告诉我我的代码返回了错误的答案,然而,当我在自定义输入上运行相同的测试用例时,我得到了评测期望的答案。
我搜索了为什么会发生这种情况,我遇到的潜在原因是全局/静态变量,然而,我没有使用任何全局/静态变量。
我解决这个问题的方法是:
- 基于价值/重量比制作一个排序后的哈希映射,其中(键,值)对是(比例,物品)。
- 对于每个物品,如果物品的重量小于可用重量,那么我们将直接将价值添加到最终答案中。
- 否则,我们将可用重量乘以比例,添加到最终答案中,然后中断。
- 最后,我们将返回答案。
我使用的代码:
### 参考用的物品类
class Item:
def __init__(self,val,w):
self.value = val
self.weight = w
class Solution:
def fractionalknapsack(self, W,arr,n):
hashmap = {(item.value / item.weight) : item for i,item in enumerate(arr) }
keys = list(hashmap.keys())
keys.sort()
sorted_hashmap = {}
keys.reverse()
for ele in keys :
sorted_hashmap[ele] = hashmap[ele]
final_ans = 0
available_weight = W
for ratio,item in sorted_hashmap.items() :
if available_weight > 0 :
if item.weight <= available_weight :
final_ans += item.value
available_weight -= item.weight
else :
final_ans += available_weight * ratio
break
else :
break
return final_ans
测试成功但提交失败的输入:
输入:
84 87
78 16 94 36 87 43 50 22 63 28 91 10 64 27 41 27 73 37 12 19 68 30 83 31 63 24 68 36 30 3 23 9 70 18 94 7 12 43 30 24 22 20 85 38 99 25 16 21 14 27 92 31 57 24 63 21 97 32 6 26 85 28 37 6 47 30 14 8 25 46 83 46 15 18 35 15 44 1 88 9 77 29 89 35 4 2 55 50 33 11 77 19 40 13 27 37 95 40 96 21 35 29 68 2 98 3 18 43 53 7 2 31 87 42 66 40 45 20 41 30 32 18 98 22 82 26 10 28 68 7 98 4 87 16 7 34 20 25 29 22 33 30 4 20 71 19 9 16 41 50 97 24 19 46 47 2 22 6 80 39 65 29 42 1 94 1 35 15
输出 :
在线评测期望输出:1078.00
我的提交输出:235.58
我自定义输入输出:1078.00
英文:
I was practicing with a GeeksForGeeks problem Fractional Knapsack:
> Given weights and values of N items, we need to put these items in a knapsack of capacity W to get the maximum total value in the knapsack.
>
> Note: Unlike 0/1 knapsack, you are allowed to break the item.
>
> ### Example 1:
>
> Input:
>
> N = 3, W = 50<br>
> values[] = {60,100,120}<br>
> weight[] = {10,20,30}<br>
>
> Output:
>
> 240.00
>
> Explanation
>
> Total maximum value of item we can have is 240.00 from the given capacity of sack.
When I submit my code, the online judge tells me my code returns a wrong answer, however when I run the same test case on custom input, I get the expected answer by the judge.
I searched as to why this happened, and the potential reasons I came across were because of Global/Static variables, however I am not using any global/static variables.
My Approach for the problem was :
- Make a sorted hashmap based on value/weight ratio, with the (key,value) pair being (ratio,item).
- For each item, if the weight of the item is less than available weight, then we will directly add the value to the final answer.
- Else we will multiply the available-weight with the ratio, add it to the final answer and break.
- Finally we will return the answer.
The code I am using :
### Item class for reference
class Item:
def __init__(self,val,w):
self.value = val
self.weight = w
class Solution:
def fractionalknapsack(self, W,arr,n):
hashmap = {(item.value / item.weight) : item for i,item in enumerate(arr) }
keys = list(hashmap.keys())
keys.sort()
sorted_hashmap = {}
keys.reverse()
for ele in keys :
sorted_hashmap[ele] = hashmap[ele]
final_ans = 0
available_weight = W
for ratio,item in sorted_hashmap.items() :
if available_weight > 0 :
if item.weight <= available_weight :
final_ans += item.value
available_weight -= item.weight
else :
final_ans += available_weight * ratio
break
else :
break
return final_ans
The input for which the test succeeds, but submission fails:
Input :
84 87
78 16 94 36 87 43 50 22 63 28 91 10 64 27 41 27 73 37 12 19 68 30 83 31 63 24 68 36 30 3 23 9 70 18 94 7 12 43 30 24 22 20 85 38 99 25 16 21 14 27 92 31 57 24 63 21 97 32 6 26 85 28 37 6 47 30 14 8 25 46 83 46 15 18 35 15 44 1 88 9 77 29 89 35 4 2 55 50 33 11 77 19 40 13 27 37 95 40 96 21 35 29 68 2 98 3 18 43 53 7 2 31 87 42 66 40 45 20 41 30 32 18 98 22 82 26 10 28 68 7 98 4 87 16 7 34 20 25 29 22 33 30 4 20 71 19 9 16 41 50 97 24 19 46 47 2 22 6 80 39 65 29 42 1 94 1 35 15
Output :
Online Judges Expected Output : 1078.00
My Submission Output : 235.58
My custom input output : 1078.00
答案1
得分: 2
这确实非常令人困惑!我查看了GeeksForGeeks运行你的代码的Python版本,撰写本文时,根据是否进行测试或提交,这些版本是不同的!
- 在测试代码时:Python 3.7.13
- 在提交代码时:Python 3.5.2
这解释了为什么在测试和提交时得到不同的结果。由于从Python 3.6开始,字典按插入顺序迭代,但在旧版本中,迭代顺序是未定义的——无论你插入项目的顺序如何,都不能保证迭代的顺序相同。
退一步,你在这里其实不需要使用字典。事实上,当两个项目恰好具有相同的比例时,使用字典会有问题,因为你会失去其中一个。
通过按比率对输入项目进行排序来解决这个问题。以下是已删除哈希映射并在输入列表上调用sort
的代码:
class Solution:
def fractionalknapsack(self, W, arr, n):
arr.sort(key=lambda item: item.value / item.weight, reverse=True)
final_ans = 0
available_weight = W
for item in arr:
if available_weight > 0:
if item.weight <= available_weight:
final_ans += item.value
available_weight -= item.weight
else:
final_ans += available_weight * item.value / item.weight
break
else:
break
return final_ans
英文:
This is indeed very confusing! I looked at the Python version that GeeksForGeeks is running your code on, and at the time of writing these versions are different depending on whether you test or submit!
- When testing the code: Python 3.7.13
- When submitting the code: Python 3.5.2
This explains why you get different results when testing versus submitting. Since Python 3.6 dictionaries are iterated in insertion order, but in older versions the iteration order is undefined -- there is no guarantee whatsoever that the order in which you inserted the items will also be the order in which the items are iterated.
Taking a step back, you should not need a dictionary here. In fact, it will be problematic when two items happen to have the same ratio, because then you will lose out on one.
Solve this by just sorting the input items by the ratio. Here is your code with the hasmap removed, and the sort
called on the input list instead:
class Solution:
def fractionalknapsack(self, W, arr, n):
arr.sort(key=lambda item: item.value / item.weight, reverse=True)
final_ans = 0
available_weight = W
for item in arr:
if available_weight > 0:
if item.weight <= available_weight:
final_ans += item.value
available_weight -= item.weight
else :
final_ans += available_weight * item.value / item.weight
break
else:
break
return final_ans
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论