2010-08-16 29 views
6

Tôi đang cố gắng kết hợp một hệ thống để đề xuất các bộ dụng cụ tiêu hao dựa trên số lượng được yêu cầu. Thách thức tôi đang gặp phải là các bộ dụng cụ có giảm giá theo khối lượng/số lượng lớn, vì vậy có thể rẻ hơn cho khách hàng để đặt hàng với số lượng lớn hơn vì giá có thể ít hơn. Ví dụ, giả sử các bộ dụng cụ có sẵn là:Giảm thiểu giá cho các đơn đặt hàng giảm giá theo khối lượng

  • 25 widget với $ 15
  • 10 widget với $ 7
  • 5 widget với $ 4
  • 1 widget cho $ 1

Ngay bây giờ, với số lượng yêu cầu là 74, thuật toán của tôi sẽ đề xuất 2 x 25, 2 x 10 và 4 x 1 = 48 đô la. Tuy nhiên, sẽ rẻ hơn nếu khách hàng chỉ cần đặt hàng 3 x 25 = 45 đô la.

Bất kỳ suy nghĩ nào về cách giải quyết vấn đề này? Tôi đang viết mã bằng C#.

Cảm ơn!

+2

tôi chắc chắn rằng người bán sẽ cung cấp cho bạn giá thấp hơn nếu bạn đặt nhiều mục. Chỉ cần nói chuyện với anh ta thay vì mã hóa ;-) –

+0

Bạn có sẵn sàng thương lượng cho tôi không? ;) – Jayoaichen

Trả lời

7

Hình như DP chuẩn (lập trình động).

// bestPrice is array of best prices for each amount 
// initially it's [0, INFINITY, INFINITY, INFINITY, ...] 

for (int i = 0; i <= 74; ++i) { 
    for (Pack pack : packs) { 
     // if (i + pack.amount) can be achieved with smaller price, do it 
     int newPrice = bestPrice[i] + pack.price; 
     if (newPrice < bestPrice[i + pack.amount]) { 
      bestPrice[i + pack.amount] = newPrice; 
     } 
    } 
} 

Câu trả lời là min(bestPrice[74], bestPrice[74 + 1], ... bestPrice[74 + 25 - 1]). Overhead 25 - 1 rõ ràng là đủ, bởi vì nếu không bạn sẽ loại bỏ một gói và số tiền vẫn sẽ là >= 74.

Một số liên kết về chủ đề này:
http://en.wikipedia.org/wiki/Dynamic_programming
http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=dynProg

chỉnh sửa
Bạn có thể tìm giải pháp tối ưu nếu bạn sửa đổi nó một chút. Thêm lastPack mảng, do đó, lastPack[i] là kích thước của gói bạn đã sử dụng để đạt được số tiền i. Tôi đoán, bạn có thể tìm ra cách cập nhật mã giả ở trên.

Khi thuật toán kết thúc, bạn có thể nhận được giải pháp như thế này

int total = 74; 
while (total > 0) { 
    // package of size lastPack[total] was used to get amount 'total' 
    // do whatever you want with this number here 

    total -= lastPack[total]; 
} 
+3

'" Từ động được chọn bởi Bellman bởi vì nó có vẻ ấn tượng, không phải vì nó mô tả cách thức hoạt động của phương pháp. " – Greg

+0

Lập trình động có lẽ nên được gọi là "lập trình được lưu trong bộ nhớ cache", hoặc một cái gì đó chỉ ra rằng nó dựa vào bộ nhớ. –

+0

Xin chào Nikita! Cảm ơn bạn vì câu trả lời. Xin vui lòng chịu với tôi khi tôi cố gắng hiểu điều này, làm thế nào để tôi biết từ số lượng gói này tôi cần? Dường như mảng bestPrice cho tôi giá tốt nhất có thể cho một số lượng nhất định, nhưng nó có cho tôi biết làm thế nào để có được số đó không? – Jayoaichen

2

Vâng, bắt đầu với đơn vị thứ 25, giá là $ 0,60/mặt hàng. Vì vậy, nếu khách hàng đặt hàng hơn 25, hãy quên các gói mà bạn đang tính toán và chỉ nhân số lượng lên $ 0,60.

+0

Xin chào NinjaCat - cảm ơn bạn đã trả lời nhanh. Thật không may những bộ dụng cụ này được đóng gói sẵn với số lượng nhất định và giá được cố định. Vì vậy, tôi không thể thay đổi giá mỗi đơn vị cho các bộ dụng cụ. Điều đó có ý nghĩa? – Jayoaichen

3

Vì vậy, bạn đang thực sự sẽ phải tự xác định tất cả các breakpoint cho các hạng mục dưới một trật tự của 25. Sau đó, về cơ bản sử dụng một bảng tra cứu loại kịch bản để xác định những gì để đặt hàng cho qty nhỏ hơn 25. AS chỉ ra trước đây này là rất tương tự như vấn đề Knapsack.

Về cơ bản mã của bạn sẽ trông giống như;

int qtyOrder; 
int qtyRemain; 
int qty25pack; 
int qty10pack; 
int qty5pack; 
int qty1pack; 

//Grab as many 25 packs as possible 
qty25pack = (qtyOrder % 25); 
qtyRemain -= qty25Pack * 25; 

//Here use your lookup table to determine what to order 
// for the qty's that are less than 25 

Bạn có thể sử dụng một số thuật toán tham lam để xác định nó khi đang di chuyển. Đó sẽ là lý tưởng nếu giá được kỳ vọng sẽ thay đổi rất nhiều.

Điều đó có thể trông giống như điền kích thước gói với đối sánh chính xác và sau đó xác định kết quả trùng khớp gần nhất với số lượng còn lại và xem liệu nó có rẻ hơn không.

Vì vậy, ví dụ:

//find the perfect product amount price 
While (qtyRemain != 0) { 
perfectPrice += (qtyRemain % nextSmallestSize) * nextSmallestPackagePrice; 
qtyRemain -= (qtyReamin % nextSmallestSize) 
} 

//Find the closest match over price 
While ((qtyRemain % nextSmallestSize) != 0){ 
closePrice += (qtyRemain % nextSmallestSize) * nextSmallestPackagePrice; 
qtyRemain -= (qtyRemain % nextSmallestSize) 
} 
//add the last price before we reached the perfect price size 
closePrice += nextSmallestPackagePrice; 

//determine lowest price 
if closePrice < perfectPrice { 
cost = closePrice; 
} 
else { 
cost = PerfectPrice; 
} 

Mã này là không có nơi gần hoàn thành nhưng phải cung cấp cho bạn một ý tưởng. Mã cũng có lẽ không phải là vĩ đại nhất.

Sửa

Các đoạn thứ hai của mã sẽ đi sau khi đoạn đầu tiên ở vị trí của lookup

+0

+1: đây là một ví dụ tuyệt vời sẽ dẫn OP đến một giải pháp tối ưu. – NotMe

+0

@Chris Sống động nhờ! đó là mục tiêu, tôi cảm thấy điểm của SO là đưa ra câu trả lời không phải giải pháp, ai cũng có thể sao chép dán. – msarchet

+0

Điều đó không phải lúc nào cũng cung cấp cho bạn giải pháp tối ưu (giống như bất kỳ giải pháp heuristic khác cho vấn đề ba lô). Ví dụ: kiểm tra giá {1: 2, 5: 7, 10: 10, 25: 24} và số tiền 30. –

Các vấn đề liên quan