Beautiful Now(暴力全排列)

                                          Beautiful Now

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

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

                                                               Statistic | Submit | Clarifications | Back

题意:给定数N(1<=N<=1e9),k(1<=k<=1e9),求对N的任意两位数交换至多k次能得到的最小与最大的数,每一次交换之后不能出现前导零。

扫描二维码关注公众号,回复: 2798797 查看本文章

题解  保存下标,全排列枚举下标 这里用到了一个非常神奇的c++内置函数next_permutation()函数 

多校的时候我看到这个题我就觉得可以用dfs暴搜一下,然而学艺不精,没搞出来,后来看了看大佬的思路发现了这么一个c++的全排列函数 然后就很简单了

这是一个c++函数,包含在头文件<algorithm>里面,下面是基本格式

1 int a[];
2 do{
3     
4 }while(next_permutation(a,a+n));

下面的代码可产生1~n的全排列。

#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

1 0 2

如果有sort()

输出为

0 1 2
0 2 1
1 0 2
1 2 0
2 0 1
2 1 0

若无

则输出为

1 0 2
1 2 0
2 0 1
2 1 0

可以发现少了许多种组合方法。

不过,仔细比较各种组合方法和有无sort()的输出,可以发现函数next_permutation()是按照字典序产生排列的,并且是从数组中当前的字典序开始依次增大直至到最大字典序。

所以全排列会从你所给序列的字典序输出比其大的全排列序列,比其小的抹掉了,因此再用这个内置函数的时候注意sort

本题因为是从0开始到cnt的字典序最小,所以可以不用sort

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <math.h>
#include <cstring>
#include <string>
#include <queue>
#include <deque>
#include <stack>
#include <stdlib.h>
#include <list>
#include <map>
#include <utility>
#include <time.h>
#include <set>
#include <bitset>
#include <vector>
#define pi acos(-1.0)
#define inf 0x3f3f3f3f
#define linf 0x3f3f3f3f3f3f3f3f
#define ms(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define ll long long
const int maxn=1e5+5;
using namespace std;
int read()
{int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
ll qpow(ll x, ll y, ll mod){ll s=1;while(y){if(y&1)s=s*x%mod;x=x*x%mod;y>>=1;}return s;}
ll a[10],vis[10],pos[10];
ll n,k;
ll cnt;
ll judge()
{
    ms(vis,0);
    ll temp=0;
    for(int i=0;i<cnt;i++)//暴力一边pos[i]里的数
    {
        if(vis[i])continue;
        ll cnt1=0;
        while(!vis[i])
        {
            cnt1++;
            vis[i]=1;
            i=pos[i];  //pos[i]排列后的位置  i排列前的位置
        }
        cnt1--;//两两交换最后肯定会多交换一下
        temp+=cnt1;
        if(temp>k)return 0;

    }
    return 1;
}
int main()
{
    int t;

    scanf("%d",&t);
    while(t--)
    {
        ll minn=INF;
        ll maxn=0;
        scanf("%lld%lld",&n,&k);
        ll temp=n;
        cnt=0;
        while(temp)
        {
            a[cnt++]=temp%10;
            temp/=10;
        }
        reverse(a,a+cnt);
        for(int i=0;i<cnt;i++)
            pos[i]=i;
        //sort(pos,pos+cnt);
        do
        {
            if(a[pos[0]]!=0 && judge())//没有前导零,并且交换的次数在k次之内
            {
                ll ans=0;
                for(int i=0;i<cnt;i++)ans=ans*10+a[pos[i]];
                if(ans>maxn)maxn=ans;
                if(ans<minn)minn=ans;

            }
        }while(next_permutation(pos,pos+cnt));

        printf("%lld %lld\n",minn,maxn);


    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41021816/article/details/81515451
今日推荐