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; }