POJ 2718 Smallest Difference
暴力DFS。
如果一个数比另一个数位数多,那么位数多的那个数从小到大排序,位数少的从大到小排序,这样能算出这种情况下的最小差值。
如果两个数字位数相同,可以枚举最高位分别是哪个数字,然后就可以确定哪个数字较大,大的那个数剩下的数字从小到大排序,小的那个数字从大到小排序。
注意处理一下前导0的问题。
#include<cstdio> #include<cstring> #include<cmath> #include<vector> #include<algorithm> using namespace std; int T; char s[1000]; long long a[20]; int tot; bool flag[20]; long long r[20],t[20]; int lenr,lent; long long ans; void read() { tot=0; while(1) { char ch=getchar(); if(ch=='\n') break; if(ch==' ') continue; a[tot++]=(long long)(ch-'0'); } } bool cmp(const long long&a,const long long &b) { return a>b; } void check() { lenr=lent=0; memset(r,0,sizeof r);memset(t,0,sizeof t); for(int i=0;i<tot;i++) { if(flag[i]==1) r[lenr++]=a[i]; else t[lent++]=a[i]; } if(lenr<lent) { sort(t,t+lent); sort(r,r+lenr,cmp); if(t[0]==0) swap(t[0],t[1]); long long sum1=0,sum2=0; for(int i=0;i<lenr;i++) sum1=sum1*10+r[i]; for(int i=0;i<lent;i++) sum2=sum2*10+t[i]; ans=min(ans,sum2-sum1); } else if(lenr==lent) { sort(t,t+lent); sort(r,r+lenr); long long sum1=0,sum2=0; for(int i=0;i<lenr;i++) { for(int j=0;j<lent;j++) { if(r[i]==0&&lenr!=1) continue; if(t[j]==0&&lent!=1) continue; sum1=r[i];sum2=t[j]; if(r[i]>t[j]) { for(int k=0;k<lenr;k++) { if(r[k]==r[i]) continue; sum1=sum1*10+r[k]; } for(int k=lent-1;k>=0;k--) { if(t[k]==t[j]) continue; sum2=sum2*10+t[k]; } ans=min(ans,sum1-sum2); } else { for(int k=lenr-1;k>=0;k--) { if(r[k]==r[i]) continue; sum1=sum1*10+r[k]; } for(int k=0;k<=lent;k++) { if(t[k]==t[j]) continue; sum2=sum2*10+t[k]; } ans=min(ans,sum2-sum1); } } } } } void dfs(int idx,int deep) { check(); if(deep==tot/2) return; for(int i=idx;i<tot;i++) {flag[i]=1;dfs(i+1,deep+1);flag[i]=0;} } int main() { scanf("%d",&T); getchar(); while(T--) { read(); ans=999999999999999; for(int i=0;i<tot;i++) {flag[i]=1;dfs(i+1,1);flag[i]=0;} printf("%lld\n",ans); } return 0; }