每组数据包括两行,第一行为一个数N (2≤N≤10),表示数字的个数。下面一行为N个不同的一位数字。
2
6
0 1 2 4 6 7
4
1 6 3 4
28
5
*****解决方案*****
【思路】 如果采用暴力穷举的方法,如果将N个数分为两组,两组中数字个数的差不超过1,这种情况下,时间复杂度为Cn n/2*(n/2)!*(n/2)!,时间复杂度比较大。
在此将问题分为几类:
(1) n=2:直接判断;
(2) n为奇数:将数字序列进行升序排序后,分别从头或者尾开始分配元素,将头元素分给第一组,将尾元素分给第二组,继而将下面的头元素分给第一组,下面的尾元素分给第二组....直到元素分配结束。
(3)n为偶数:枚举非零数字a[i]作为x的最高位,a[i+1]作为y的最高位,从右往左取k-1位加入x,从左往右取k-1位加入y,打擂台更新答案。(打擂台的意思即为,先选取一个擂主,继而挑战者上台挑战擂主,挑战成功便成为擂主,否则擂主守擂成功,然后下一个挑战者上台。。)
代码:
1 #include <iostream> 2 #include <algorithm> 3 using namespace std; 4 int a[15]; 5 int n; 6 int abs(int x){ return (x<0?-x:x); } 7 int work1(){ 8 if (a[1]==0) swap(a[1],a[2]); 9 int s1=0,s2=0; 10 for (int i=1;i<=n/2+1;i++) s1=s1*10+a[i]; 11 for (int i=n;i>=n/2+2;i--) s2=s2*10+a[i]; 12 return abs(s1-s2); 13 } 14 int work2(){ 15 int book[15];//标志元素是否被使用过,使用过其值为1,否则为0 16 int s1,s2; 17 int ans=(1<<31)-1; 18 for (int i=2;i<=n;i++) 19 if (a[i-1]){ 20 s1=a[i],s2=a[i-1]; 21 memset(book,0,sizeof(book)); 22 book[i]=book[i-1]=1; 23 int l=1,r=n; 24 for (int j=1;j<=(n-2)/2;j++){//每一轮选出俩个数字 25 while (book[l]) l++; 26 while (book[r]) r--; 27 book[l]=book[r]=1; 28 /*for(int i = 1;i<15;i++) 29 printf("%d ",book[i]);*/ 30 s1=s1*10+a[l];s2=s2*10+a[r]; 31 32 }/* 33 printf("%d %d\n",s1, s2);*/ 34 ans=min(ans,abs(s1-s2)); 35 } 36 return ans; 37 } 38 int main(){ 39 int t; 40 cin>>t; 41 while (t--){ 42 scanf("%d",&n); 43 for (int i=1;i<=n;i++) scanf("%d",&a[i]); 44 sort(a+1,a+1+n); 45 if (n==2) { printf("%d\n",a[2]-a[1]);continue; } 46 if (n%2==1) printf("%d\n",work1()); else printf("%d\n",work2()); 47 } 48 }
原文:https://www.cnblogs.com/baixinyu/p/11808808.html