题意:
给你一个数字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);
}
}