HDU 6351 Beautiful Now 【DFS】(2018 MUTC 5)

 

Beautiful Now

Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 1768    Accepted Submission(s): 662


 

Problem Description

Anton has a positive integer n, however, it quite looks like a mess, so he wants to make it beautiful after k swaps of digits.
Let the decimal representation of n as (x1x2⋯xm)10 satisfying that 1≤x1≤9, 0≤xi≤9 (2≤i≤m), which means n=∑mi=1xi10m−i. In each swap, Anton can select two digits xi and xj (1≤i≤j≤m) and then swap them if the integer after this swap has no leading zero.
Could you please tell him the minimum integer and the maximum integer he can obtain after k swaps?

Input

The first line contains one integer T, indicating the number of test cases.
Each of the following T lines describes a test case and contains two space-separated integers n and k.
1≤T≤100, 1≤n,k≤109.

Output

For each test case, print in one line the minimum integer and the maximum integer which are separated by one space.

Sample Input

5

12 1

213 2

998244353 1

998244353 2

998244353 3

Sample Output

12 21

123 321

298944353 998544323

238944359 998544332

233944859 998544332

题目大意:

输入一个T,表示有T组数据,每组数据输入一个int范围内的数字n和一个正整数k。意思是给你k次操作,每次操作可以交换n中任意两个数。问能得到的最小值和最大值分别是多少。

题解:

题目的输入样例告诉我们,是小于等于k次,并不一定要满足k次,你也可以理解为自己可以和自己交换。
有多种解法,这里就不介绍最暴力的全排列算法了,全部的可能都试了一遍,复杂度O( 9!)

我们这里介绍用dfs来解决这道题目,dfs是学习算法的入门,相信大家都有学习过。

首先我们先解决求最小值的问题,为了方便,数字n我们应该用字符串来接收输入会比较好。

按照题目要求,我们的第一位数(不能有前导0)应该是最小的。思路要清晰明确,一步步来,我们要找最小值,应该要遍历一次所有数,找到里面最小的。

int pos = 0;//第一个数字是在下标为0的地方
for(int i=1;i<len;i++)
	if(tep[pos]>tep[i]&&tep[i]!='0')//第一位不能有前导0
		pos = i;

如果最小的数在第一位上,那我们不用管它,继续下一位往下找最小值;如果不是在第一位上的话,那我们要把最小的值交换到第一位上,然后才dfs到第二位上去找最小值,一直递归按照这样的思路走下去。当到了k次后,就判断一下此时得到的值和之前的值相比谁大谁小,如果现在的值更小,就更新一下答案,继续dfs寻找,直到符合条件的都走过了一边后,得到的一定是最小值。

if(pos!=0){//如果最小值不在第一位上,则找到最小值,和它进行交换,并且k-1
	for(int i=1;i<len;i++){
//因为可能有多种情况,所以要for循环判断,下意识以为只需要取最后一个最小值的同学就错了
		if(tep[i]==tep[pos]){
			swap(tep[i],tep[0]);
			dfs(1,k-1);
			swap(tep[i],tep[0]);//因为这只是其中一种情况,所以要恢复原状
		}
	}
}else
	dfs(1,k);//如果是在第一位上,那我们继续看下一位,k值不变

dfs递归跳出条件为: 

if(k==0||pos>=len){
//dfs递归跳出条件为操作次数剩余为0或者下标超过范围(就是符合了条件,值不能再小了,不需要再交换了)
	if(strcmp(ans,tep)>0)
		strcpy(ans,tep);//如果找到更小的,更新一下
	return;//递归终点
}

附上AC代码:

#include <bits/stdc++.h>
using namespace std;
int len,t,k;
char s[12],tep[12],ans[12];
void dfs(int pos,int k,int type){ 
	if(k==0||pos>=len){
		if(type==1){
			if(strcmp(ans,tep)>0)
				strcpy(ans,tep);
		} 			
		else
			if(strcmp(ans,tep)<0)
				strcpy(ans,tep);	
		return;
	}
	int x = pos;
	for(int i=x+1;i<len;i++){
		if(type==1){
			if(tep[x]>tep[i])
				x = i;
		}
		else
			if(tep[x]<tep[i])
				x = i;
	}	
	if(pos!=x){
		for(int i=x;i<len;i++){
			if(tep[i]==tep[x]){
				swap(tep[i],tep[pos]);
				dfs(pos+1,k-1,type);
				swap(tep[i],tep[pos]);
			}
		}
	}else
		dfs(pos+1,k,type);
}
void solve(int pos,int type){
	if(pos!=0){
		for(int i=1;i<len;i++){
			if(tep[i]==tep[pos]){
				swap(tep[i],tep[0]);
				dfs(1,k-1,type);
				swap(tep[i],tep[0]);
			}
		}
	}else
		dfs(1,k,type);
}
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%s %d",s,&k);
		len = strlen(s);
		strcpy(tep,s);strcpy(ans,s);
		int pos = 0;
		for(int i=1;i<len;i++)
			if(tep[pos]>tep[i]&&tep[i]!='0')
				pos = i;
		solve(pos,1);
		printf("%s ",ans);
		strcpy(tep,s);strcpy(ans,s);
		pos = 0;
		for(int i=1;i<len;i++)
			if(tep[pos]<tep[i]&&tep[i]!='0')
				pos = i;
		solve(pos,2);
		printf("%s\n",ans);
	}
}
发布了22 篇原创文章 · 获赞 19 · 访问量 3545

猜你喜欢

转载自blog.csdn.net/KnightHONG/article/details/81482230