CodeForces - 95B (dfs)

题目链接:http://codeforces.com/problemset/problem/95/B

题意:

  给你一个数字,要你求出不小于它的最小的超级完美数。超级完美数的定义是:这个数字每一位都是4或者7,并且4的总位数要等于7的总位数。

思路:

  我刚开始推算的思路是:要是这个数有奇数位,那么就只需要加一位,加了一个位数的话肯定是比原来的数要大的,就只需要求出加了一位之后的最小超级完美数,即前一半位数是4,后一半位数是7。如果是偶数位的话,先将这个数与当前位数的最大的超级完美数比较,即前一半7后一半4的那个数,如果这个数比当前位最大的超级完美数还要大,说明还要加两位,加位的答案就是前一半4后一半7。否则的话,就从当前位数最小的超级完美数开始遍历,找出最小的不小于它的超级完美数。(事实证明,前面的想法都是没问题的,问题就出在这里)因为超级完美数都是相等数量的4和相等数量的7组成的,所以我就想着字典序全排列的话,从小到大遍历过去判断就行了,但是这样子做是会超时的,因为字典序全排列这个过程时间消耗很大。改进的方法就是,不依次与超级完美数进行比较,而是直接处理当前这个数,将它变成符合要求的超级完美数。然后看了下别人写的,感觉这个dfs的写法挺好的,避免了我之前的一些重复操作。下面就给出我自己的TLE代码和别人用dfs写的AC代码吧。

代码:

 1 /*————————————————————AC代码————————————————————*/
 2 #include<iostream>
 3 #include<cstring>
 4 using namespace std;
 5 const int maxn = 1e5 + 10;
 6 int len;
 7 char str[maxn];
 8 char ans[maxn];
 9 bool dfs(int pos, int sum1, int sum2, bool flag)    //pos指当前位数,sum1指4的总个数,sum2指7的总个数,flag标识符
10 {
11     if(pos >= len)
12         return true;
13     if(flag)    //前面有位数变大了,那么后面的数就按一半4一半7排列
14     {
15         for(int i = 0; i < sum1; i++)
16             ans[pos++] = '4';
17         for(int i = 0; i < sum2; i++)
18             ans[pos++] = '7';
19         return true;
20     }
21     if(sum1 && str[pos] <= '4')
22     {
23         if(dfs(pos + 1, sum1 - 1, sum2, str[pos] != '4'))    //遍历到一个比4小的数,并且将这个位数的数变成4是可行的
24         {
25             ans[pos] = '4';
26             return true;
27         }
28     }
29     if(sum2 && str[pos] <= '7')
30     {
31         if(dfs(pos + 1, sum1, sum2 - 1, str[pos] != '7'))    //遍历到一个比7小的数,并且将这个位数的数变成7是可行的
32         {
33             ans[pos] = '7';
34             return true;
35         }
36     }
37     return false;    //没有比4和7小的数,说明当前位数不够,要加两位
38 }
39 
40 int main()
41 {
42     cin >> str;
43     len = strlen(str);
44     if(len & 1 || !dfs(0, len / 2, len / 2, 0))
45     {
46         if(len & 1)        //奇数位加一位
47             len++;
48         else    //dfs返回false加两位
49             len += 2;
50         //加位的话一半4一半7就行
51         int i;
52         for(i = 0; i < len / 2; i++)
53             ans[i] = '4';
54         for(i ; i < len; i++)
55             ans[i] = '7';
56     }
57     cout << ans << endl;
58     return 0;
59 }

 

 1 /*————————————————————TLE代码————————————————————*/
 2 #include<stdio.h>
 3 #include<stdlib.h>
 4 #include<algorithm>
 5 #include<cstring>
 6 
 7 const int maxn = 1e5 + 10;
 8 char num[maxn];
 9 char tmp[maxn];
10 
11 int main()
12 {
13     while(scanf("%s", num) != EOF)
14     {
15         int len = strlen(num);
16         if(len % 2)    //奇数位的话,+1位,前一半是4,后一半是7
17         {
18             for(int i = 0; i < (len + 1) / 2; i++)
19             {
20                 printf("4");
21             }
22             for(int i = (len + 1) / 2; i < len + 1; i++)
23             {
24                 printf("7");
25             }
26             printf("\n");
27         }
28         else
29         {
30             for(int i = 0; i < (len / 2); i++)
31             {
32                 tmp[i] = '7';
33             }
34             for(int i = (len / 2); i < len; i++)
35             {
36                 tmp[i] = '4';
37             }
38             //如果比当前位数情况下最大的超级完美数还要大,就要加两位
39             if(strcmp(num, tmp) == 1)
40             {
41                 //加位前一半4,后一半7
42                 for(int i = 0; i < ((len + 2) / 2); i++)
43                 {
44                     printf("4");
45                 }
46                 for(int i = ((len + 2) / 2); i < len + 2; i++)
47                 {
48                     printf("7");
49                 }
50                 printf("\n");
51             }
52             else
53             {
54                 //位数固定,4和7的数量固定,字典序全排列列举比较,找最小的不低于的,就从最小的开始
55                 for(int i = 0; i < (len / 2); i++)
56                 {
57                     tmp[i] = '4';
58                 }
59                 for(int i = (len / 2); i < len; i++)
60                 {
61                     tmp[i] = '7';
62                 }
63                 if(strcmp(num, tmp) != 1)
64                 {
65                     for(int i = 0; i < len; i++)
66                         printf("%c", tmp[i]);
67                     printf("\n");
68                 }
69                 else
70                 {
71                     while(std::next_permutation(tmp, tmp + len))
72                     {
73                         if(strcmp(num, tmp) != 1)
74                         {
75                             for(int i = 0; i < len; i++)
76                                 printf("%c", tmp[i]);
77                             printf("\n");
78                             break;
79                         }
80                     }
81                 }
82             }
83         }
84     }
85     return 0;
86 }

 

转载于:https://www.cnblogs.com/friend-A/p/9436763.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值