题意:
给出一段数字,在更换k次后,找到最大值和最小值。
题解:
这道题没办法用贪心算,只能用dfs或者全排列爆搜,题目给的范围只有10位数,我们可以全部列出来全排列
10*9*8*7*6*5*4*3*2*1 暴力列出所有就是10!次
我们用下标来进行排列变换,
来排列好的值按照1 2 3 4。。。顺序变回原样,就可以记录此时的times,保证times<=k,然后找到对应所代表的值,并记录最大最小值。
例如2 4 6 1 3 5 变回原样的操作是
1 4 6 2 3 5 times=1
1 2 6 4 3 5 times=2
1 2 3 4 6 5 times=3
1 2 3 4 5 6 times=4
代码:
#include<bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
int k;
int maxx;
int minn;
int len;
int num[15],s__s[15],now[15];
void update(){
if(num[now[1]]==0){
return;
}
int times=0;
int ans=0;
for(int i=1;i<=len;i++){
s__s[i]=now[i];
}
for(int i=1;i<=len;i++){
ans=ans*10+num[now[i]];
if(s__s[i]!=i){
times++;
if(times>k){
return;
}
for(int j=i+1;j<=len;j++){
if(s__s[j]==i){
s__s[i]^=s__s[j]^=s__s[i]^=s__s[j];
break;
}
}
}
}
minn=min(ans,minn);
maxx=max(ans,maxx);
}
int main(){
int t;
scanf("%d",&t);
while(t--){
char s[20];
memset(s__s,0,sizeof(s__s));
memset(now,0,sizeof(now));
scanf("%s",s);
scanf("%d",&k);
len=strlen(s);
for(int i=1;i<=len;i++){
num[i]=s[i-1]-'0';
now[num[i]]++;
s__s[num[i]]++;
}
if(k>=len-1){
for(int i=1;i<=9;i++){
if(s__s[i]){
printf("%d",i);
s__s[i]--;
break;
}
}
for(int i=0;i<=9;i++){
while(s__s[i]){
printf("%d",i);
s__s[i]--;
}
}
printf(" ");
for(int i=9;i>=0;i--){
while(now[i]){
printf("%d",i);
now[i]--;
}
}
printf("\n");
continue;
}
for(int i=1;i<=len;i++){
now[i]=i;
}
maxx=0;
minn=inf;
update();
while(next_permutation(now+1, now+1+len)){
update();
}
printf("%d %d\n",minn,maxx);
}
}