洛谷P2525 Uim的情人節禮物·其之壱(組合數學/上一個全排列)

題目

給定長度爲n(n<=9)的全排列,

輸出比該全排列上一個字典序的全排列,

不存在輸出ERROR

思路來源

https://www.luogu.com.cn/problemnew/solution/P2525

題解

組合數學惡補第二彈,orz這個可是洛谷入門題

考慮上一個字典序,一定出現在某一位比當前全排列小了,且是最靠後的一位

對於相鄰的正序對,無法交換其順序,所以一定是從後往前的第一個逆序對

若a[i-1]>a[i],則可以把a[i-1]調小,變成字典序更小的全排列,

所以找到x\epsilon[i,n)範圍內滿足a[x]<a[i-1]且值最大的那個位置x,將其與a[i-1]交換,

交換之後,起到了降字典序的目的,後面的數應降序排列,使當前的字典序最大

代碼1

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=10;
int n,a[N],b[N],cnt;
bool ok;
void solve(int x){//[x,n)
	int mx=-1,pos=-1;
	for(int i=x+1;i<n;++i){//<a[x]的最大的 從最小的逆序一位開始調小 
		if(a[i]<a[x]){
			if(a[i]>mx){
				mx=a[i];
				pos=i;
			}
		}
	}
	swap(a[pos],a[x]);
	sort(a+x+1,a+n,greater<int>());//後面的降序即可 表示此時的最大 
}
int main(){
	scanf("%d",&n); 
	for(int i=0;i<n;++i){
		scanf("%d",&a[i]);
	}
	for(int i=n-1;i;--i){
		if(a[i-1]>a[i]){
			solve(i-1);
			for(int j=0;j<n;++j){
				printf("%d%c",a[j]," \n"[j==n-1]);
			}
			ok=1;
			break;
		}
	}
	if(!ok)puts("ERROR");
	return 0;
}

代碼2(prev_permutation)

用STL水,調用該函數,若上一個全排列存在,則會使ai變成上一個全排列,否則返回假

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=10;
int n,a[N],b[N],cnt;
int main(){
	scanf("%d",&n); 
	for(int i=0;i<n;++i){
		scanf("%d",&a[i]);
	}
	if(!prev_permutation(a,a+n))puts("ERROR");
	else{
		for(int i=0;i<n;++i){
		printf("%d%c",a[i]," \n"[i==n-1]);
		}
	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章