Tại sao vấn đề knapsack là giả đa thức?


87

Tôi biết đó Knapsacklà NP-hoàn thành trong khi DP có thể giải quyết được. Họ nói rằng giải pháp DP là pseudo-polynomial, vì nó là cấp số nhân trong "độ dài của đầu vào" (tức là số bit cần thiết để mã hóa đầu vào). Thật không may, tôi đã không nhận được nó. Ai đó có thể giải thích pseudo-polynomialđiều đó cho tôi từ từ được không?


Câu trả lời:


90

Thời gian chạy là O (NW) đối với bài toán bao đựng không bị ràng buộc với N mục và bao có kích thước W. W không phải là đa thức về độ dài của đầu vào, đó là điều khiến nó trở thành giả đa thức.

Coi W = 1.000.000.000.000. Chỉ cần 40 bit để biểu diễn số này, vì vậy kích thước đầu vào = 40, nhưng thời gian chạy tính toán sử dụng hệ số 1.000.000.000.000 là O (2 40 ).

Vì vậy, thời gian chạy được nói chính xác hơn là O (N.2 bit trong W ), là cấp số nhân.

Cũng thấy:


1
Liên kết số 3 đề cập đến "Độ phức tạp của lập trình động cho vấn đề 0-1 knapsack" đã chết.
dev_nut

1
Xin lỗi, tôi không hiểu. Giả sử nếu chúng ta có một thuật toán với độ phức tạp thời gian O (N), thì chúng ta có O (2 ^ (bit trong N)), là cấp số nhân? Cảm ơn ~
Lusha Li

3
@LushaLi Điều này đã giúp tôi: youtube.com/watch?v=9oI7fg-MIpE . Nếu N là một mảng mà mỗi phần tử có đầu vào kích thước tối đa cố định (giả sử mỗi phần tử trong mảng không quá 32 bit) và bạn chạy vòng lặp for trên mảng này một lần, thì đó là một thuật toán thời gian đa thức trong đầu vào kích thước N của mảng. Tuy nhiên, nếu N là một số nguyên và bạn chạy một vòng qua N, thì N không bị giới hạn và tăng theo cấp số nhân về số bit cần thiết để biểu diễn nó. Vì vậy, một vòng lặp for đơn giản trên N, thực ra là theo cấp số nhân. Lưu ý rằng trong trường hợp của mảng, kích thước của mỗi phần tử trong mảng là giới hạn trên.
max_max_mir

Tôi không bị thuyết phục. Có rất nhiều thuật toán có cùng thuộc tính không phải là "đa thức giả". Giả sử, độ phức tạp của Sieve of Eratosthenes (hoặc bất kỳ công cụ tìm số nguyên tố nào khác)?
Ofir A.

31

Trong hầu hết các vấn đề của chúng tôi, chúng tôi đang giải quyết các danh sách lớn các số phù hợp với các kiểu dữ liệu int / float tiêu chuẩn. Do cách hầu hết các bộ xử lý được xây dựng để xử lý các số 4-8 byte tại một thời điểm mà không mất thêm chi phí (liên quan đến các số hơn là vừa với, chẳng hạn như 1 byte), chúng tôi hiếm khi gặp phải sự thay đổi trong thời gian chạy từ việc mở rộng số lượng của chúng tôi hoặc trong phạm vi mà chúng ta gặp phải trong các vấn đề thực tế - vì vậy yếu tố chi phối vẫn chỉ là số lượng điểm dữ liệu tuyệt đối, n hoặc m yếu tố mà chúng ta đã quen thuộc.

(Bạn có thể tưởng tượng rằng ký hiệu Big-O đang ẩn một hệ số không đổi chia ra 32 hoặc 64 bit-mỗi dữ liệu, chỉ để lại số điểm dữ liệu bất cứ khi nào mỗi số của chúng ta phù hợp với nhiều bit đó hoặc ít hơn )

Nhưng hãy thử làm lại với các thuật toán khác để hành động trên các tập dữ liệu liên quan đến các số nguyên lớn - các số yêu cầu nhiều hơn 8 byte để biểu diễn - và xem điều đó ảnh hưởng gì đến thời gian chạy. Độ lớn của các con số liên quan luôn tạo ra sự khác biệt, ngay cả trong các thuật toán khác như sắp xếp nhị phân, một khi bạn mở rộng ra ngoài vùng đệm của các bộ xử lý thông thường an toàn sẽ cung cấp cho chúng tôi "miễn phí" bằng cách xử lý các lô 4-8 byte.

Mẹo với thuật toán Knapsack mà chúng ta đã thảo luận là nó nhạy cảm bất thường (so với các thuật toán khác) đối với độ lớn của một tham số cụ thể, W. Thêm một bit vào W và bạn tăng gấp đôi thời gian chạy của thuật toán. Chúng tôi chưa thấy loại phản ứng mạnh mẽ đó đối với những thay đổi về giá trị trong các thuật toán khác trước thuật toán này, đó là lý do tại sao có vẻ như chúng tôi đang đối xử với Knapsack theo cách khác - nhưng đó là phân tích chính xác về cách nó phản ứng theo kiểu không đa thức để thay đổi kích thước đầu vào.


8

Thời gian chạy của thuật toán Knapsack không chỉ bị ràng buộc bởi kích thước của đầu vào (n - số mục) mà còn về độ lớn của đầu vào (W - dung lượng của gói) O (nW) theo cấp số nhân. được biểu diễn trong máy tính ở dạng nhị phân (2 ^ n). Độ phức tạp tính toán (tức là cách xử lý được thực hiện bên trong máy tính thông qua các bit) chỉ liên quan đến kích thước của các đầu vào chứ không phải độ lớn / giá trị của chúng .

Bỏ qua danh sách giá trị / trọng lượng trong giây lát. Giả sử chúng ta có một thể hiện với dung lượng knapsack 2. W sẽ lấy hai bit trong dữ liệu đầu vào. Bây giờ chúng ta sẽ tăng dung lượng gói dữ liệu lên 4, giữ phần còn lại của đầu vào. Đầu vào của chúng tôi chỉ tăng thêm một bit, nhưng độ phức tạp tính toán đã tăng lên gấp đôi. Nếu chúng tôi tăng dung lượng lên 1024, chúng tôi sẽ chỉ có 10 bit đầu vào cho W thay vì 2, nhưng độ phức tạp đã tăng lên theo hệ số 512. Độ phức tạp theo thời gian tăng theo cấp số nhân với kích thước của W trong biểu diễn nhị phân (hoặc thập phân) .

Một ví dụ đơn giản khác giúp tôi hiểu khái niệm đa thức giả là thuật toán kiểm tra tính nguyên sơ ngây thơ. Đối với một số n cho trước, chúng ta đang kiểm tra xem nó có chia đều cho mỗi số nguyên trong phạm vi 2..√n không, vì vậy thuật toán thực hiện √ (n − 1) bước. Nhưng ở đây, n là độ lớn của đầu vào, không phải là kích thước.

                     Now The regular O(n) case

Ngược lại, tìm kiếm một mảng cho một phần tử đã cho sẽ chạy theo thời gian đa thức: O (n). Nó mất nhiều nhất n bước và ở đây n là kích thước của đầu vào (độ dài của mảng).

[xem tại đây]

Tính toán các bit cần thiết để lưu trữ số thập phân


3
Vì vậy, đối với ví dụ tìm kiếm cuối cùng của bạn, tại sao không coi n là nhị phân? nếu n = 1024, nó cũng chỉ mất 10bits, vì vậy nó không phải là đa thức giả?
user1024,

7

Theo cách tôi hiểu điều này là công suất sẽ là O (W) nếu đầu vào công suất là một mảng [1,2, ..., W] , có kích thước là W. Nhưng đầu vào công suất thì không. một mảng số, thay vào đó nó là một số nguyên. Độ phức tạp về thời gian là về mối quan hệ với kích thước của đầu vào. Các kích thước của một số nguyên là không giá trị của số nguyên, nhưng số lượng các bit đại diện cho nó. Sau đó chúng ta chuyển số nguyên W này thành mảng [1,2, ..., W] trong thuật toán, khiến mọi người nhầm tưởng W là kích thước, nhưng mảng này không phải là đầu vào, chính là số nguyên.

Hãy coi đầu vào là "một mảng nội dung" và kích thước là "bao nhiêu nội dung trong mảng". Đầu vào mục thực sự là một mảng gồm n mục trong mảng nên size = n. Đầu vào dung lượng KHÔNG phải là một mảng W số trong đó, mà là một số nguyên duy nhất , được biểu diễn bằng một mảng các bit log (W). Tăng kích thước của nó lên 1 (thêm 1 bit có nghĩa), W tăng gấp đôi nên thời gian chạy tăng gấp đôi, do đó độ phức tạp của thời gian theo cấp số nhâ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.