題意:
給你一個數字n(1<=n<=1e9),通過k次交換其中的數字使其達到最小和最大。
題解:
如果從第一個就開始往後面排序,最小步驟達到最小是 n的位數-1 ,所以我們可以讓 k >= n的位數-1 情況都輸出排序後的最小,最大值。
如果小於,從前往後貪心貪大值換小值是不可以的,如:425111 3 ==> 111425。
所以我們可以通過暴力枚舉所有排序,最大也就是10!。
在遍歷每一個排序的時候,把其變回原來的排序需要多少步,如果需要的步驟大於k則可以跳出循環進行下一個排序,如果滿足條件,我們可以記錄這個排序的值,與最大的值和最小的值進行對比。
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <bitset>
#include <stack>
#include <cmath>
#include <deque>
#include <queue>
#include <list>
#include <set>
#include <map>
#define mem(a) memset(a, 0, sizeof(a))
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
int num1[20], num2[20], num3[20], k, maxx, minn, len;
void update(){
if(num1[num3[1]] == 0){
return;
}
for(int i = 1; i <= len; i++){
num2[i] = num3[i];
}
int sum = 0, t = 0;
for(int i = 1; i <= len; i++){
sum = sum*10+num1[num3[i]];
if(num2[i] != i){
for(int j = i+1; j <= len; j++){
if(num2[j] == i){
num2[i] ^= num2[j] ^= num2[i] ^= num2[j];
t++;
if(t > k){
return;
}
break;
}
}
}
}
if(t > k){
return;
}
minn = min(minn, sum);
maxx = max(maxx, sum);
}
int main(){
int T;
scanf("%d", &T);
for(int t = 0; t < T; t++){
char s[20];
mem(num2);
mem(num3);
scanf("%s %d", s+1, &k);
for(int i = 1 ; s[i] != '\0'; i++){
num1[i] = s[i]-'0';
num2[num1[i]]++;
num3[num1[i]]++;
}
len = strlen(s+1);
if(k >= len-1){
for(int i = 1; i <= 9; i++){
if(num2[i]){
printf("%d", i);
num2[i]--;
break;
}
}
for(int i = 0; i <= 9; i++){
while(num2[i]){
printf("%d", i);
num2[i]--;
}
}
printf(" ");
for(int i = 9; i >= 0; i--){
while(num3[i]){
printf("%d", i);
num3[i]--;
}
}
printf("\n");
continue;
}
for(int i = 1; i <= len; i++){
num3[i] = i;
}
minn = inf;
maxx = 0;
update();
while(next_permutation(num3+1, num3+1+len)){
update();
}
printf("%d %d\n", minn, maxx);
}
}