next_permutation函式

胖柚の工作室發表於2024-03-31

例題1:P1088 [NOIP2004 普及組] 火星人

如果採用樸素的方法,每次都把火星人的排列初始化為原始排列再計算次數肯定會 \(\sf TLE\)

#include <bits/stdc++.h>

const int N = 1e4 + 5;
int a[N], b[N];
int n, m, cnt, t;

bool check(int x[], int y[]) {
	for (int i = 0; i < n; i++) {
		if (x[i] != y[i]) return false;
	}
	return true;
}

int main()
{
	std::cin >> n >> m;
	for (int i = 0; i < n; i++) std::cin >> a[i];
	
	for (int i = 0; i < n; i++) b[i] = a[i];
	std::sort(b, b + n);
	
	do {
		if (check(a, b)) break;
		cnt++;
	}while(std::next_permutation(b, b + n));
	
	cnt += m;
	std::sort(b, b + n);
	
	do {
		if (t == cnt) {
			for (int i = 0; i < n; i++) std::cout << b[i] << " ";
			break;
		}
		t++;
	}while(std::next_permutation(b, b + n));
}

image

所以應該從當前排列(就是火星人手指表示的那個序列)開始,做 \(m\) 次排列,即找按順序排列的全排列中,排在當前序列之後 \(m\) 個的那個序列。

\(AC\) 程式碼:

#include <cstdio>
#include <algorithm>

const int N = 1e4 + 5;
int a[N], n, m;

int main()
{
	scanf("%d%d", &n, &m);
	for (int i = 0; i < n; i++) scanf("%d", &a[i]);
	
	while (m--) std::next_permutation(a, a + n); 
	
	for (int i = 0; i < n; i++) printf("%d ", a[i]);
	return 0;
}

例題2:HDU 1027

題目大意為輸出序列 \(1 \sim N\) 的第 \(m\) 個全排列。

#include <cstdio>
#include <algorithm>

const int N = 1010;
int a[N];
int n, m, cnt;

int main()
{
	while (scanf("%d%d", &n, &m) != EOF) {
		for (int i = 0; i < n; i++) a[i] = i + 1;
		cnt = 0;
		do {
			if (cnt == m - 1) { 
				for (int i = 0; i < n; i++) printf("%d ", a[i]);
				puts("");
				break;
			}
			cnt++;
		}while(std::next_permutation(a, a + n));			
	}
	return 0;
}

相關文章