FZU 2111 Min Number

暴力

训练的题目,给出一个数字(最长1000位即10^1000),给出m表示交换次数(每次可以交换任意两位的数字),问交换后得到的最小数字。注意,数字不能有前导0,另外有m次交换机会,但不必全部用完,只要交换到最小数字了就可以退出

为了得到最小数字,就是从高位开始,不断找最小的数字放到高位(但第一位要特殊处理不能为0)。如果现在使第i位最小,从第i到最后一位扫描找到最小值然后交换然后交换次数减1,如果刚好第i位就是最小值,则不交换,直接跳过,所以交换次数不能减1。如果m>len,即大于数字的位数,那么显然后面的交换机会都是多余的,最多交换len次就可以退出了

 

所以结束枚举的条件是,以为枚举了全部len位或者交换机会用完了

一开始算出时间复杂度以为暴力超时,其实没有,1000*100*100=10^7,刚好没超

不够程序跑出了0ms也真的是……

#include <cstdio>

#include <cstring>

#define N 1010

#define INF 0x3f3f3f3f



int a[N];

char str[N];

int m,n;



void solve(int m)

{

    int p=2;

    while(p<=n && m>0)

    {

        int min=INF , x=p;

        for(int i=p; i<=n; i++)

            if(a[i]<min)

            { min=a[i]; x=i;}

        if(x==p) 

            p++;

        else  

        {

            a[p]=a[p]^a[x];

            a[x]=a[p]^a[x];

            a[p]=a[p]^a[x];

            p++;

            m--;

        }

    }

    for(int i=1; i<=n; i++)

        printf("%d",a[i]);

    printf("\n");

}



int main()

{

    int T;

    scanf("%d",&T);

    while(T--)

    {

        scanf("%s%d",str+1,&m);

        if(m==0)

        {

            printf("%s\n",str+1);

            continue;

        }

        n=strlen(str+1);

        for(int i=1; i<=n; i++)

            a[i]=str[i]-'0';

        if(m>n) m=n;



        int min=INF,x=1;

        for(int i=1; i<=n; i++)

            if(a[i]!=0 && a[i]<min)

            { min=a[i]; x=i; }

        if(x==1)

        {

            solve(m);

            continue;

        }



        a[x]=a[x]^a[1];

        a[1]=a[x]^a[1];

        a[x]=a[x]^a[1];

        solve(--m);

    }

    return 0;

}

 

你可能感兴趣的:(number)