Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# 1011. Capacity To Ship Packages Within D Days
## STEP1
- 何も見ずに解いてみる
- 船のキャパシティを range として用意し、days 以内で運び出せるかどうかを判定する。True となる最小のキャパシティを探索する。

```python
import bisect


MAX_WEIGHT = 500
MAX_WEIGHT_LENGTH = 50_000


class Solution:
def shipWithinDays(self, weights: List[int], days: int) -> int:
def can_ship_within_days(ship_capacity: int) -> bool:
num_days = 1
total_weight_at_a_day = 0
for weight in weights:
if weight > ship_capacity:
return False
total_weight_at_a_day += weight
if total_weight_at_a_day <= ship_capacity:
continue
num_days += 1
total_weight_at_a_day = weight
return num_days <= days

return bisect.bisect_left(
range(MAX_WEIGHT * MAX_WEIGHT_LENGTH + 1),
True,
key=can_ship_within_days
)
```

## STEP2
### プルリクやドキュメントを参照
- range を bisect_left の引数として良いかは自信がなかった。
- https://docs.python.org/3/library/stdtypes.html#typesseq-range
- range は空間計算量 O(1) で、 common sequence operations としてランダムアクセスも実装されていそうなので、動く。

- https://github.com/olsen-blue/Arai60/pull/44/files
- 探索区間について、[max(weights), sum(weights)] でよい。船のキャパの下限を、全ての荷物一つが乗るサイズとすると、空の船に荷物が乗らない状況を考えなくて済む。
- days が 0 の場合、STEP1のコードは MAX_WEIGHT * MAX_WEIGHT_LENGTH + 1 を返す。意味はないので 0 は ValueError とした方がよい。

```python
import bisect


class Solution:
def shipWithinDays(self, weights: List[int], days: int) -> int:
if days <= 0:
raise ValueError("days must be positive.")

def can_ship_within_days(ship_capacity: int) -> bool:
days_required = 1
total_weight = 0
for weight in weights:
total_weight += weight
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

個人的にはtotal_weight_at_a_dayと、a_dayが入っていた方がわかりやすい方が気もしますが冗長さとの加減が難しいですね

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます。そうですね、a_day ではない合計を求めてもしょうがないので冗長かと思い除いてみました。

if total_weight <= ship_capacity:
continue
days_required += 1
total_weight = weight
return days_required <= days

return bisect.bisect_left(
range(sum(weights) + 1),
True,
lo=max(weights),
key=can_ship_within_days
)
```

練習として2分探索を書く。
```python
class Solution:
def shipWithinDays(self, weights: List[int], days: int) -> int:
if days <= 0:
raise ValueError("days must be positive.")

def can_ship_within_days(ship_capacity: int) -> bool:
days_required = 1
total_weight = 0
for weight in weights:
total_weight += weight
if total_weight <= ship_capacity:
continue
days_required += 1
total_weight = weight
return days_required <= days

low = max(weights)
high = sum(weights)
while low < high:
middle = (low + high) // 2
if can_ship_within_days(middle):
high = middle
else:
low = middle + 1
return low
```
## STEP3
### 3回ミスなく書く
```python
import bisect


class Solution:
def shipWithinDays(self, weights: List[int], days: int) -> int:
if days <= 0:
raise ValueError("days must be positive")

def can_ship_within_days(ship_capacity: int) -> bool:
total_weight = 0
days_required = 1
for weight in weights:
total_weight += weight
if total_weight <= ship_capacity:
continue
days_required += 1
total_weight = weight
return days_required <= days

return bisect.bisect_left(
range(sum(weights) + 1),
True,
lo=max(weights),
key=can_ship_within_days
)
```

3分,3分,3分で3回Accept