Code liệt kê hoán vị của n bằng phương pháp sinh bị sai

Đề bài là liệt kê hoán vị của n bằng phương pháp sinh c++.Em làm và cứ bị sai.mọi người giúp em với ạ.Em cám ơn nhiều

#include<iostream>
using namespace std;

	int n,x[100],y,z;
	

int Init() {

	for(int i=1;i<=n;i++) {
		x[i]=i;
	}
}

bool check() {
	for(int i=n;i>=1;i--) 
		if(x[i]!=n-i+1) return false;
	return true;
}

void result() {
	for(int i=1;i<=n;i++) {
		cout<<x[i]<<" ";
	}
	cout<<endl;
}


void swap(int &a,int &b) {
	int c;
	c=a;
	a=b;
    b=c;
}


void sinh() {
	int i;
	for(int i=n;i>=1;i--) {
		if(x[i]>x[i-1]) {
		    for(int j=n;j>=i;j--) {
		    	if(x[j]>x[i-1]) {
		    		swap(x[i-1],x[j]);
		    		break;
				}
			}	
		}
	}
	int s=n;
	int r=i; 
	while (s<r) {
		swap(x[s],x[r]);
	    r++;
	    s--;
	}
}


int main() {
	cin>>n;
	Init();
    while(check()!=false) {
	sinh();
	result();
    }
    result();
}

Để như này thì sao chạy được. :slight_smile:

Với lại thuật toán sinh của bạn bị sai rồi.

Và để vòng lặp như :point_down: sẽ không in được cấu hình đầu tiên.

Sửa lại thành
void sinh() {
    int i = n;
    while (i > 0 && x[i] < x[i - 1]) i--;
    if (!i) return;
    int j =  n;
    while (j > 0 && x[j] < x[i - 1]) j--;
    swap(x[i - 1], x[j]);
    for (j = n; j > i; j--, i++) swap(x[i], x[j]);
}

int main() {
    cin >> n;
    Init();
    result();
    do {
        sinh();
        result();
    } while (!check());
    return 0;
}

Test: https://rextester.com/IAV36812

4 Likes

Hoán vị đầu tiên xem như trường hợp đặc biệt, sau đó ta dùng do… while :slight_smile:

do {
   sinh();
   result();
} while(!check());
5 Likes

Thêm cái result() trước do . . while là in được hết. :slight_smile:

E fix rồi, cảm ơn anh. :blush: :blush:

4 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?