题意:
给你一个n和k,表示n内的数字可以交换k次,然后让你找到他的最小和最大值输出。
题解:
BFS暴搜就好了,但是要处理一下剪枝,不然会超时或者超内存(我也不知道为什么会出现超内存的。。),代码写的丑。。请laoda们别吐槽。。。
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
const int MAXN=11;
char s[MAXN];
int n,MIN,MAX,k,c[MAXN],e[MAXN];
struct node
{
int t;
int num;
int pos;
}now,last;
bool cmp(int b,int c)
{
return b>c;
}
void bfs1()//查找最大值
{
last.t=0;
last.num=MAX;
last.pos=0;
queue<node>q;
while(!q.empty())
q.pop();
q.push(last);
while(!q.empty())
{
now=q.front();
q.pop();
now.t++;
if(now.t>k)
continue;
int p=now.num;
// printf("p=%d\n",p);
for(int i=n-1;i>=0;i--)
c[i]=p%10,p/=10;
p=now.num;
for(int i=now.pos;i<n;i++)
for(int j=i+1;j<n;j++)
if(c[i]<c[j])//要加上这个剪枝,表示的是高位的值要小于低位的值才进行交换。
{
// int A=pow(10,n-1-i),B=pow(10,n-1-j);
int A=e[n-1-i],B=e[n-1-j];
// printf("%d %d %d %d\n",n-1-j,n-1-i,A,B);
// printf("%d !!%d %d @@!!!",now.num,A,B);
now.num=now.num-c[i]*A-c[j]*B+c[i]*B+c[j]*A;
// printf("%d %d %d %d %d @@ %d %d %d %d\n",now.num,i,j,c[i],c[j],c[i]*A,c[j]*B,c[j]*A,c[i]*B);
// swap(c[i],c[j]);
MAX=max(MAX,now.num);
now.pos++;
q.push(now);
now.pos--;
now.num=p;
// swap(c[i],c[j]);
}
}
}
void bfs2()//查找最小值
{
last.t=0;
last.num=MIN;
last.pos=0;
queue<node>q;
while(!q.empty())
q.pop();
q.push(last);
while(!q.empty())
{
now=q.front();
q.pop();
now.t++;
if(now.t>k)
continue;
int p=now.num;
// printf("p=%d\n",p);
for(int i=n-1;i>=0;i--)
c[i]=p%10,p/=10;
if(c[0]==0)
continue;
p=now.num;
for(int i=now.pos;i<n;i++)
for(int j=i+1;j<n;j++)
if(c[i]>c[j])//要加上这个剪枝,表示的是高位的值要大于低位的值才进行交换。
{
// int A=pow(10,n-1-i),B=pow(10,n-1-j);
int A=e[n-1-i],B=e[n-1-j];
// printf("%d %d %d %d\n",n-1-j,n-1-i,A,B);
// printf("%d !!%d %d @@!!!",now.num,A,B);
now.num=now.num-c[i]*A-c[j]*B+c[i]*B+c[j]*A;
// printf("%d %d %d %d %d @@ %d %d %d %d\n",now.num,i,j,c[i],c[j],c[i]*A,c[j]*B,c[j]*A,c[i]*B);
swap(c[i],c[j]);
if(c[0]==0){//找最小值这里要注意一下就是不能有前导零。
swap(c[i],c[j]);
now.num=p;
continue;
}
MIN=min(MIN,now.num);
// printf("@@%d\n",MIN);
now.pos++;
q.push(now);
now.pos--;
now.num=p;
swap(c[i],c[j]);
}
}
}
int main()
{
e[0]=1;
for(int i=1;i<=10;i++)
e[i]=e[i-1]*10;
int t,m;
scanf("%d",&t);
while(t--)
{
scanf("%s%d",s,&k);
MAX=0,MIN=0;
n=strlen(s);
for(int i=0;i<n;i++){
c[i]=s[i]-'0';
MAX=MAX*10+c[i];
MIN=MAX;
}
// printf("%s %d %d\n",s,MAX,MIN);
if(k>=n-1)//k大于等于数值的长度-1的话说明可以完全交换,但是还是要注意不能出现前导零。
{
// printf("fake\n");
// for(int i=0;i<n;i++)
// printf("%d",c[i]);
// printf("fake\n");
sort(c,c+n);
if(c[0]==0)
{
int pos=0;
for(int i=0;i<n;i++)
if(c[i]!=0){
pos=i,printf("%d",c[i]);
break;
}
for(int i=0;i<n;i++)
if(i!=pos)
printf("%d",c[i]);
}
else
{
for(int i=0;i<n;i++)
printf("%d",c[i]);
}
printf(" ");
sort(c,c+n,cmp);
for(int i=0;i<n;i++)
printf("%d",c[i]);
printf("\n");
continue;
}
bfs1();
bfs2();
printf("%d %d\n",MIN,MAX);
}
}