Nếu tôi đã hiểu chính xác câu hỏi, một chút suy nghĩ sẽ thuyết phục bạn rằng ngay cả lập trình động cũng không cần thiết - giải pháp hoàn toàn không đáng kể.
Đây là câu hỏi như tôi hiểu nó: bạn đang đưa ra một mảng a [1] .. a [M] của 0s và 1s, và bạn được phép hoạt động của mẫu S k, trong đó S k có nghĩa là lật các phần tử N thành [k], [k + 1], ... a [k + N-1]. Điều này chỉ được xác định cho 1≤k≤M-N + 1, rõ ràng.
Bằng cách thực hiện một chuỗi các thao tác này S k, bạn muốn tiếp cận trạng thái của tất cả 0 hoặc tất cả 1s. Chúng tôi sẽ giải quyết cho cả hai cách riêng biệt và lấy số nhỏ hơn. Vì vậy, giả sử chúng tôi muốn làm cho tất cả 0 (trường hợp khác, tất cả 1s, là đối xứng).
Các quan trọng ý tưởng là bạn sẽ không bao giờ muốn thực hiện bất kỳ hoạt động S k nhiều hơn một lần (làm việc đó hai lần tương đương với không làm gì cả), và đó là thứ tự của các hoạt động không quan trọng. Vì vậy, câu hỏi là chỉ để xác định tập hợp con của các hoạt động bạn thực hiện, và điều này rất dễ dàng để xác định. Nhìn vào [1]. Nếu đó là 0, thì bạn biết bạn sẽ không thực hiện S . Khác, bạn biết bạn phải thực hiện S (vì đây là thao tác duy nhất sẽ lật [1]), do đó hãy thực hiện nó - thao tác này sẽ chuyển tất cả các bit từ [1] sang [N]. Bây giờ nhìn vào một [2] (sau khi hoạt động này). Tùy thuộc vào việc nó là 1 hay 0, bạn biết liệu bạn sẽ thực hiện S hay không. Và cứ thế - bạn có thể xác định có bao nhiêu thao tác (và cái nào) để thực hiện, trong thời gian tuyến tính.
Chỉnh sửa: Mã giả được thay thế bằng mã C++, vì có thẻ C++. Xin lỗi vì mã xấu xí; khi ở "chế độ cuộc thi" tôi hoàn nguyên về thói quen thi đấu. :-)
#include <iostream>
using namespace std;
const int INF = 20000000;
#define FOR(i,n) for(int i=0,_n=n; i<_n; ++i)
int flips(int a[], int M, int N, int want) {
int s[M]; FOR(i,M) s[i] = 0;
int sum=0, ans=0;
FOR(i,M) {
s[i] = (a[i]+sum)%2 != want;
sum += s[i] - (i>=N-1?s[i-N+1]:0);
ans += s[i];
if(i>M-N and s[i]!=0) return INF;
}
return ans;
}
int main() {
int M = 6, N = 3;
int a[] = {1, 0, 0, 1, 0, 0};
printf("Need %d flips to 0 and and %d flips to 1\n",
flips(a, M, N, 0), flips(a, M, N, 1));
}
1. Đây có phải là bài tập về nhà không? 2. M và N lớn cỡ nào? (Ví dụ, một thuật toán O (M 2^N) có hoạt động không?) 3. Tiếng Anh của bạn hoàn toàn ổn. Tôi không nghĩ vấn đề này có một danh hiệu nổi tiếng. – ShreevatsaR
Vấn đề có đảm bảo luôn có giải pháp không?Đối với 1 0 1 và N = 3 ví dụ không có giải pháp. Thuật toán có nên giải thích cho những trường hợp này hay không? – IVlad
Có thể bạn sẽ nhận được nhiều phản hồi hơn nếu bạn thử sự cố, đặt một số mã hoặc mã giả trong câu hỏi của bạn rồi hỏi ý kiến. – thebretness