Beautiful Now
Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 2386 Accepted Submission(s): 866
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
Source
2018 Multi-University Training Contest 5
看了好多博客,发现有用搜索的,有用全排列的,在这里全排列是可以暴力过的
最大的难度是次数怎样去实现,用下标来实现,当访问过的就标记为1,没访问过的标记为0,显然访问过的不能再进行下去,跳出循环,这样去卡它的次数
用全排列的好处是,它会自动排好序,例如
#include <stdio.h>
#include <algorithm>
using namespace std;
int main(){
int n;
while(scanf("%d",&n)&&n){
int a[1000];
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
sort(a,a+n);//可以自行测试一下删除后的结果
do{
for(int i=0;i<n;i++)
printf("%d ",a[i]);
printf("\n");
}while(next_permutation(a,a+n));
}
return 0;
}
3
7 5 3
3 5 7
3 7 5
5 3 7
5 7 3
7 3 5
7 5 3
只需判断出符合次数条件,且在此基础上还是最大的,最小的即可
全排列下标,因为字符可以重复,若不用此方法,计算次数的时候可能会WA
#include<bits/stdc++.h>
using namespace std;
int vis[20];
int xb[20];//下标
int k,len;
char s[20];//字符数组
int cheak()//检查交换次数
{
fill(vis,vis+len,0);每个字符长度不一样,所以用fill会将不同长度的字符数组置为0
int p=0;
for(int i=0;i<len;i++)
{
if(vis[i]) continue;
int ans=0;
while(vis[i]==0)
{
ans++;
vis[i]=1;
i=xb[i];
}
p=p+ans-1;
if(p>k) return 0;//可能在小于k的时间就已经找到最小和最大值
}
return 1;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%s %d",s,&k);
len=strlen(s);
for(int i=0;i<len;i++)
{
xb[i]=i;//下标初始化
}
int max1=0;
int min1=1e9+5;
do
{
if(s[xb[0]]!='0'&&cheak())
{
int sum=0;
for(int i=0;i<len;i++)
{
sum=sum*10+s[xb[i]]-'0';
}
if(sum<min1)
{
min1=sum;
}
if(sum>max1)
{
max1=sum;
}
}
}while(next_permutation(xb,xb+len));//全排列
printf("%d %d\n",min1,max1);
}
return 0;
}
怎样去查找它的次数
i 0 1 2 3
数组a[i] 1 4 7 5
下标b[i] 0 1 2 3
i 0 1 2 3
交换一次 下标b[i] 0 1 3 2
a[i] 1 4 5 7
可以发现如果下标2,3改变,则去看当i=2的时候,下标对应的是b[2]=3,
将b[2]的值作为下标去检查,此时当i=3时看是否b[3]与原序列改变
这个规律之前我也没发现,真的很神奇。。。。