(DFS、全排列)POJ-2718 Smallest Difference

题目地址

简要题意:

  给若干组数字,每组数据是递增的在0——9之间的数,且每组数的个数不确定。对于每组数,输出由这些数组成的两个数的差的绝对值最小是多少(每个数出现且只出现一次)。

思路分析:

  对于n个数,必定为分成两个位数分别为n/2和n-n/2的数时才可能取得差的绝对值最小。两组数分别进行全排列比较大小,这样比较次数最大为(10A5)*(5A5)=10!,在可以接受的范围内。

参考代码:

  

 1 #include<stdio.h>
 2 #include<cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 typedef long long ll;
 7 const int INF=0x3f3f3f3f;
 8 int a[12],t,n,ans,b[12];
 9 bool vi[12];
10 void check(int x)
11 {
12     int len=0,y=0,i;
13     for(i=0;i<n;i++)
14     {
15         if(!vi[i])
16             b[len++]=a[i],y=y*10+a[i];
17     }
18     if(b[0]!=0||len==1)//如果只有1位的话首位(也就是唯一的那一位)可以为0
19             ans=min(ans,abs(x-y));
20     while(next_permutation(b,b+len))//全排列借用next_permutation函数
21     {
22         y=0;
23         for(i=0;i<len;i++)
24         {
25             y=y*10+b[i];
26         }
27                 if(b[0]!=0||len==1)
28             ans=min(ans,abs(x-y));
29     }
30 }
31 void dfs(int k,int an)
32 {
33 
34     if(k==n/2)
35     {
36         check(an);
37         return;
38     }
39     else
40     {
41         int i;
42         for(i=0;i<n;i++)
43         {
44             if(!vi[i])
45             {
46                 if(a[i]==0&&k==0&&n>3)//只有一位且此时为0的情况
47                     continue;
48                 vi[i]=true;
49                 dfs(k+1,an*10+a[i]);
50                 vi[i]=false;
51             }
52         }
53     }
54 }
55 int main()
56 {
57     char tem;
58     while(~scanf("%d ",&t))//%d后面加上空格可以不用再额外getchar读去换行符
59     {
60     while(t--)
61     {
62         n=0;
63         while((tem=getchar())!='\n')//注意读入的方法
64         {
65             if(tem==' ')
66                 continue;
67             a[n++]=tem-'0';
68         }
69         ans=INF;
70         memset(vi,false,sizeof(vi));
71         dfs(0,0);
72         printf("%d\n",ans);
73     }
74     }
75     return 0;
76 }

 

posted @ 2016-12-05 21:45  perplex  阅读(612)  评论(0编辑  收藏  举报