2018 Multi-University Training Contest 5 B. Beautiful Now

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

因为N最多只有10位,且给了2500ms,当时觉得可以枚举全排列,再判断前导零和最少交换次数。

最少交换次数是(每个循环节中的个数-1)之和。

当时想的是全排列N的每位数,但是这样会出现一个问题:N中可能出现相同的数,这样求循环节中元素个数就会很困难。‘

其实应该对下标进行全排列,因为下标是不可能相同的,这样就可以O(len) 地计算出每个排列的最少交换次数。然后取符合条件的最小最大的数为答案。

转一份别人的代码(dfs):

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<vector>
#include<cmath>
#include<map>
#include<set>
#include<stack>
#define INF 0x3f3f3f3f
#define EXP 0.00000001
#define MOD 1000000007
#define MAXN 100005
#define PI acos(-1.0)
#define ltree 2*id,ll,mid
#define rtree 2*id+1,mid+1,rr
#define mem(a) memset(a,0,sizeof(a))
typedef long long LL;

using namespace std;

string mx;
string mi;
string s;
int k;
int len;

void dfs(int now,int step)
{
    if(step>k||now==len)
        return;
    mx=max(mx,s);
    if(s[0]!='0')
        mi=min(mi,s);
    dfs(now+1,step);
    for(int i=now+1;i<len;++i)
    {
        swap(s[now],s[i]);
        dfs(now+1,step+1);
        swap(s[now],s[i]);
    }
}

int main()
{
    int t;
    cin>>t;
    while(t--)
    {

        cin>>s>>k;
        len=s.size();
        mx=mi=s;
        dfs(1,0);
        for(int i=1;i<len;++i)
        {
            swap(s[0],s[i]);
            dfs(1,1);
            swap(s[0],s[i]);
        }
        cout<<mi<<" "<<mx<<endl;
    }
    return 0;
}
 


 

猜你喜欢

转载自blog.csdn.net/FACEYc/article/details/81461084
今日推荐