Làm thế nào là vấn đề chọn Pizza Pizza‍ Được giải quyết bằng cách sử dụng các kỹ thuật lập trình động?


9

Vấn đề chọn pizza của Winkler:

  • Một miếng bánh pizza hình tròn gồm các nlát, trong đó lát icó diện tích S_i, tức là diện tích khác nhau cho mỗi miếng bánh.
  • Người ăn Alice và Bob thay phiên nhau chọn những lát, nhưng thật thô lỗ khi tạo ra nhiều khoảng trống trong chiếc bánh (xem xét nó không được phép).
    • Do đó, mỗi người ăn bị hạn chế lấy một trong hai lát liền kề với vùng mở. Alice đi trước, và cả hai người ăn đều tìm kiếm càng nhiều bánh càng tốt.

Làm thế nào một thuật toán lập trình động xác định Alice ăn bao nhiêu bánh, nếu cả Alice và Bob chơi hoàn hảo để tối đa hóa mức tiêu thụ pizza của họ?

Sự hiểu biết của tôi:

Trong một vấn đề DP chung, chúng tôi tiếp tục tìm kiếm các vấn đề phụ có thể được hình dung bằng cách sử dụng cây đệ quy hoặc, chặt chẽ hơn, bằng cách sử dụng DAG. Ở đây, tôi không tìm thấy bất kỳ sự dẫn dắt nào để tìm ra các vấn đề phụ ở đây.

Ở đây, đối với một tập hợp S_i nhất định, chúng ta cần tối đa hóa diện tích lát cắt mà Alice ăn. Điều này sẽ phụ thuộc vào việc chọn hoán vị các lát Pizza trong số các hoán vị (n-1). Chọn một lát cắt diện tích tối đa trong số hai tùy chọn có sẵn trong mỗi n \ 2 lượt Alice nhận được, sẽ cho chúng ta tổng diện tích lát cắt cho một hoán vị. Chúng ta cần tìm diện tích lát cho tất cả các hoán vị như vậy. Và sau đó tối đa trong số này.

Ai đó có thể giúp tôi về cách đi tiếp?

Câu trả lời:


5

Bắt đầu bằng cách xem xét các lát chỉ được đặt trên một hàng và bạn có thể chọn từ một trong hai đầu. Trong trường hợp này, giả sử đến lượt bạn chọn thì rõ ràng đó pizzaAmount(slices)

  1. Nếu không có kết quả pizza còn lại là 0
  2. Nếu chỉ có một kết quả lát là lát đó
  3. Nếu có ít nhất hai lát thì kết quả là:

(sử dụng cú pháp Python)

max(slices[0] + sum(slices[1:]) - pizzaAmount(slices[1:]),
    slices[-1] + sum(slices[:-1]) - pizzaAmount(slices[:-1]))

nói cách khác, bạn nên xem xét cả hai lựa chọn thay thế và sau khi lấy lát của bạn, bạn sẽ nhận được tất cả các bánh pizza còn lại ngoại trừ kết quả của cuộc gọi đệ quy (vì bạn của bạn sẽ sử dụng cùng một chiến lược).

Bạn có thể thực hiện điều này với DP (hoặc ghi nhớ) vì mảng thực sự cố định và bạn chỉ có thể coi là tham số chỉ số lát đầu tiên và cuối cùng.

Để giải quyết vấn đề đầy đủ ban đầu, bạn chỉ cần thử tất cả các lát như bắt đầu lát và chọn một lát tối đa hóa kết quả.


Cảm ơn "6502". Tôi có thể hình dung vấn đề tốt hơn bằng cách sử dụng gợi ý "xem xét các lát chỉ được đặt trên một hàng và chọn từ một trong hai đầu". Quan hệ tái phát được đưa ra là chăm sóc sự lựa chọn tối ưu của đối thủ, là tốt. Tôi sẽ sớm đăng một thuật toán chính thức. Cảm ơn các bạn!!

Chỉ tò mò, thứ tự phức tạp của thuật toán này là gì? 0 (n * 2 ^ n)?

@Akron: Đây là những gì nó sẽ có nếu không có cách tiếp cận lập trình động hoặc ghi nhớ. Tuy nhiên, bạn có thể lợi dụng thực tế là kết quả của pizzaAmountnó chỉ phụ thuộc vào chỉ số bắt đầu và dừng của các lát còn lại chứ không phụ thuộc vào chuỗi bánh pizza mà bạn và bạn của bạn đã ăn để bạn có thể lưu trữ kết quả trong ma trận để tránh tính toán lại. Do đó, thứ tự của thuật toán là O (n ** 2).
6502

Nếu bất cứ ai vẫn đang cố gắng để hiểu, liên kết này có một lời giải thích rất hay.
Amit Shekhar

3

Đối với một phần của pizza, hãy xác định F(i,j)tối đa số người mà miếng bánh đầu tiên có thể ăn. Những lát bánh pizza (i,j)là:

if i <= j than slices i, i+1, ..., j-1, j
if i > j than slices i, i+1, ..., n-1, n, 1, 2, ..., j-1, j
and we don't define it for whole pizza, abs(i-j) < n-1

Xác định R(i,j)(còn lại bao nhiêu cho người thứ hai) là sum(S_x, x in slices(i,j)) - F(i,j).

Với:

F(i,i) = S_i,
F(i,j) = max( S_i + R(i+1,j), S_j + R(i,j-1) ),

tối đa Alice có thể ăn được tính bằng:

max( S_i + F(i+1, (i-1) if i > 1 else n) ).
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.