Đây là một gợi ý để bạn bắt đầu. Áp dụng các thuật toán lập trình động tiêu chuẩn để liệt kê tập hợp các phân vùng của một số nguyên và thêm một số logic để kiểm tra xem các thuật toán nào cho phép thực hiện thay đổi duy nhất bằng cách kiểm tra lặp lại tất cả các khoản tiền, thực hiện thay đổi và xác minh tính duy nhất.
Chi tiết hơn một chút: Giả sử bạn có . Cho một số với , làm thế nào bạn có thể xác định một tiểu trình của mà tổng hợp với ? Làm thế nào bạn có thể kiểm tra xem Subultiset đó là duy nhất? Cố gắng thích ứng các kỹ thuật lập trình động tiêu chuẩn để tạo ra sự thay đổi . (Xem thêm câu hỏi này .)i 1 ≤ i ≤ n S iSi1≤i≤nSi
Với một đa , làm thế nào bạn có thể kiểm tra xem nó có thỏa mãn điều kiện thứ hai hay không, tức là, liệu mọi số từ 1 đến có thể được biểu diễn duy nhất dưới dạng tổng của một hàm con của (điều kiện thay đổi duy nhất) không? Điều này sẽ khá dễ dàng, nếu bạn đã giải quyết cái trước.n SSnS
hãy để biểu thị danh sách các đa thỏa mãn cả hai điều kiện của bạn. Nếu bạn biết , làm thế nào bạn có thể sử dụng thông tin đó để xây dựng ? Ở đây bạn có thể muốn điều chỉnh các kỹ thuật lập trình động tiêu chuẩn để liệt kê các phân vùng của một số nguyên.P ( 1 ) , P ( 2 ) , Mạnh , P ( n ) P ( n + 1 )P(n)P(1),P(2),…,P(n)P(n+1)
Đây là một cách tiếp cận có thể sẽ tốt hơn.
Giả sử là một multiset thỏa mãn cả hai điều kiện của bạn (cho ). Làm thế nào chúng ta có thể mở rộng nó để có được nhiều có nhiều yếu tố hơn? Nói cách khác, làm thế nào chúng ta có thể xác định tất cả các cách để thêm một phần tử nữa vào , để có được một nhiều phần mới thỏa mãn cả hai điều kiện của bạn (đối với một số )?SnTSTn′
Trả lời: nếu có thể được biểu thị dưới dạng tổng của một số phần tử của , thì không có điểm nào để thêm nó vào : điều đó sẽ khiến vi phạm điều kiện duy nhất. Vì vậy, chúng ta có thể liệt kê tất cả các số nguyên mà không thể được diễn tả như một khoản tiền của một số các yếu tố của ; mỗi cái là một thứ có khả năng có thể được thêm vào để có được một trang mới sẽ thỏa mãn cả hai điều kiện (đối với một số khác ).xSSTxSSTn
Ngoài ra, có thể liệt kê các số nguyên nào có thể được biểu diễn dưới dạng tổng của một số phần tử của và không thể sử dụng lập trình động. Bạn xây dựng một mảng hai chiều của booleans, trong đó là đúng nếu có một cách để biểu thị số nguyên là tổng của một số Các phần tử đầu tiên của (chỉ các phần tử đầu tiên của đủ điều kiện được sử dụng; trong đó đã được sắp xếp, do đó và ). Lưu ý rằngA [ 1 Lọ | S | , 1 ... n ] Một [ iSA[1…|S|,1…n]A[i,j]jiSiSSS={s1,s2,…,sk}s1≤s2≤⋯≤skA[i,j]có thể tính toán bằng các giá trị của : đặc biệt, nếu hoặc nếu không. Điều này cho phép chúng ta xác định tất cả các số đó là ứng cử viên để được thêm vào .A[1…i−1,1…j−1]A[i,j]=A[i−1,j]∨A[i−1,j−si]j>siA[i,j]=A[i−1,j]S
Tiếp theo, đối với mỗi phần mở rộng ứng viên của (thu được bằng cách thêm một phần tử vào ), chúng tôi muốn kiểm tra xem thỏa mãn cả hai điều kiện hay không. Hãy biểu thị tổng của các yếu tố của , và tổng của các yếu tố của . Chúng ta cần phải kiểm tra xem tất cả các số nguyên trong phạm vi có thể được thể hiện dưới dạng một khoản tiền của một số các yếu tố của . Điều này cũng có thể được giải quyết bằng lập trình động, sử dụng các thuật toán tiêu chuẩn để thực hiện thay đổi. (Trong thực tế, nếu bạn vẫn có mảngS S T n S n 'TSSTnSn′Tn+1,n+2,…,n′TAđã đề cập ở trên, bạn có thể dễ dàng mở rộng nó một chút để giải quyết vấn đề này: chúng tôi biến nó thành một mảng , tiếp tục điền vào tất cả các mục bổ sung và đảm bảo rằng đều đúng.) Vì vậy, bây giờ chúng ta có thể liệt kê tất cả các đa mục mở rộng bởi một yếu tố duy nhất và đáp ứng cả hai điều kiện.A[1…|T|,1…n′]T SA[|T|,n+1],A[|T|,n+2],…,A[|T|,n′]TS
Điều này ngay lập tức gợi ý một thuật toán để liệt kê tất cả các multisets thỏa mãn điều kiện của bạn, cho tất cả lên đến một số ràng buộc, giả sử . Chúng ta sẽ có một mảng , trong đó lưu trữ tất cả các đa số có tổng bằng 5, và nói chung, lưu trữ tập hợp của tất cả các đa số có tổng bằng .n n ≤ 20 P [ 1 ... 20 ] P [ 5 ] S P [ n ] S nSnn≤20P[1…20]P[5]SP[n]Sn
Tiếp theo, chúng ta có thể điền vào lặp đi lặp lại. Bắt đầu bằng cách đặt để chỉ chứa một multiset . Tiếp theo, với mỗi (đếm từ 1 đến 20), với mỗi , hãy liệt kê tất cả các phần mở rộng có thể của (sử dụng các kỹ thuật ở trên), hãy biểu thị tổng các phần tử của , và chèn vào nếu nó chưa xuất hiện và nếu .P [ 1 ] { 1 } n S ∈ P [ n ] T S n ′ T TP[n]P[1]{1}nS∈P[n]TSn′TTn ' ≤ 20P[n′]n′≤20
Điều này nên được thực hiện khá. Chúc may mắn! Chúc vui vẻ! Làm việc thông qua các chi tiết sẽ là một bài tập học tập tốt trong lập trình động.