CodeForces - 95B(DFS)
题目链接:http://codeforces.com/problemset/problem/95/B
题目大意:给你一个正整数n (1 ≤ n ≤ 10100000),求不大小于它的超级幸运数字(超级幸运数字就是只含有数字4和数字7,并且4和7的数目相同)
例:
Sample Input
4500
47
Sampule Output
4747
47
解题思路:压根没想到用DFS,开始就想着,先判断数字的个数是否是个奇数,如果是个奇数就很好办,直接加一位数字,前一半是4后一半是7,当它的数字个数为偶数时就模拟从高位一个一个判断的,然后发现好复杂就放弃了。然后又想用全排列就变得很简单了,但是这数字太大了可能又10的5次方位,大一点的数肯定就算不出来了。看了大佬的代码才知道还可以用DFS。
如果数字个数是奇数的情况下可以直接输出,如果是偶数我们就用DFS从高位开始搜索,含有4个参数,第一个参数是当前搜索的位置,还要有一个参数判断数字是否已经比原来那个更大了,还有两个参数是分别用来记录当前4和7可用的个数,初始时4和7可用的个数都是原来数长度的一半。对于数的每一位我们只需要判断两种情况,是否<=4,如果=4继续搜索,如果小于4,直接变成4这时数就比原来更大了,后面还有的位就分别先填充可用的4,再填充可用的7,这用就能保证它最小了。如果大于4,就判断是否<=7就可以了,和小于4同理操作。然后还有一种情况就是,所有数字都大于7,这时候就要多加两个数位,前一半是4后一半是7就够了。
附上代码:
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 using namespace std;
6 char n[100005];
7 char ans[100005];
8 int len;
9
10 bool dfs(int pos,int cnt4,int cnt7,bool toup)
11 {
12 if(pos==len) return true; //一直搜索到数字的尾部也未退出,说明它本身就是超级幸运数字
13 if(toup) //如果已经变大了就把没用用完的4和7填完,先填4再填7,返回
14 {
15 for(int i=0;i<cnt4;i++)
16 ans[pos++]='4';
17 for(int i=0;i<cnt7;i++)
18 ans[pos++]='7';
19 return true;
20 }
21 if(n[pos]<='4'&&cnt4)
22 {
23 if(dfs(pos+1,cnt4-1,cnt7,n[pos]<'4'))
24 {
25 ans[pos]='4'; //如果是<4将改为改成4
26 return true;
27 }
28 }
29 if(n[pos]<='7'&&cnt7)
30 {
31 if(dfs(pos+1,cnt4,cnt7-1,n[pos]<'7'))
32 {
33 ans[pos]='7'; //如果<7将该位改成7
34 return true;
35 }
36 }
37 return false; //未搜索到大于原数的
38 }
39
40 int main()
41 {
42 while(cin>>n)
43 {
44 len=strlen(n);
45 if(len%2||!dfs(0,len/2,len/2,false)) //如果数位是奇数,或者搜搜索到的,直接先填4再填7
46 {
47 int x=(len%2?(len+1)/2:(len+2)/2);
48 for(int i=1;i<=x;i++)
49 cout<<4;
50 for(int i=1;i<=x;i++)
51 cout<<7;
52 cout<<endl;
53 continue;
54 }
55 cout<<ans<<endl;
56 }
57 return 0;
58 }