AcWing 带分数 dfs

Posted fx1998

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AcWing 带分数 dfs相关的知识,希望对你有一定的参考价值。

技术图片

技术图片

方法一:

最原始,最暴力,耗时4秒,但是是最好想的思路。

生成1~9的全排列。对于每个全排列,依次枚举a,b,c的位数。枚举三个数的位数时,就相当于在9个数形成的8个空里,插入俩隔板。

所以时间复杂度大致是全排列个数9!乘以8个空里选俩的组合数:c(8,2)。

估计是10,160,640。不过按电脑1秒计算量是10^7看的话,运行4秒大致时间复杂度是4*10^7左右。?

能得出正确答案,不过绝对会超时。

技术图片

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int n, ans;
 4 int a[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
 5 int getNum(int l, int r) { //求出这个数
 6     int res = 0;
 7     for (int i = l; i <= r; i++) {
 8         res = res * 10 + a[i];
 9     }
10     return res;
11 }
12 bool check(int a, int b, int c) { //判断n == a + b / c
13     if (b % c != 0) {
14         return false;
15     }
16     if (a + b / c != n) {
17         return false;
18     }
19     return true;
20 }
21 int main() {
22     cin >> n;
23     do {
24         for (int i = 0; i <= 6; i++) { 
25             for (int j = i + 1; j <= 7; j++) { // c必须大于0,所以要给c留出一位
26                 int a = getNum(0, i);
27                 int b = getNum(i + 1, j);
28                 int c = getNum(j + 1, 8);
29                 if (check(a, b, c)) {
30                     ans++;
31                 }
32             }
33         }
34     } while (next_permutation(a, a + 9));
35     cout << ans << endl;
36     return 0;
37 }

方法二:

优化版。1.2秒左右,按理说还是会超时,不过是目前为止的最优解。

技术图片

 

方法一中是直接枚举a,b,c的位数,自变量是三个,没有用到题目给出的性质。

方法二把等式n = a + b / c两边乘上c,得c * n = c * a + b。

n是给出的,枚举a和c就好,b可以直接算出,自变量是两个了。

n最多只有6位。

搜索思路:

  先枚举a,对于每个枚举的a再枚举c,最后再判断等式是否成立。就是递归搜索a时在每一个递归搜索树的叶子节点后再接上另一个递归搜索树用来递归搜索c,然后在这个树的叶子节点上判断一下等式是否成立。

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 20; 
 4 typedef long long ll;
 5 int n;
 6 int ans;
 7 bool st[N], bk[N]; //判重数组和备份数组 
 8 bool check(int a, int c) { //判断a和c是不是满足要求
 9      ll b = (ll)c * n - (ll)c * a; 
10      if (!a || !b || !c) { //a,b,c不能为0 
11          return false;
12      }
13      memcpy(bk, st, sizeof st); //把st复制给bk
14      while (b) { //拆出b的每一位 
15          int x = b % 10;
16         b /= 10;
17         if (!x || bk[x]) { //如果x为0或者x已经出现过,就不合法 
18             return false;
19         }
20         bk[x] = true;
21      } 
22      for (int i = 1; i <= 9; i++) { //判断9个数是不是全都出现过 
23          if (!bk[i]) { 
24              return false;
25          }
26      }
27      return true;
28 }
29 void dfs_c(int u, int a, int c) {
30     if (u == n) { //如果已经用完了n个数字 
31         return;
32     }
33     if (check(a, c)) {
34         ans++;
35     } 
36     for (int i = 1; i <= 9; i++) {
37         if (!st[i]) {
38             st[i] = true;
39             dfs_c(u + 1, a, c * 10 + i);
40             st[i] = false;
41         }
42     }
43 } 
44 void dfs_a(int u, int a) { //参数一:u表示已经用了多少个数字, 参数二:表示a的值 
45     if (a >= n) { //a,b,c三个数字至少有一位 
46         return;
47     }
48     //对于a<n的每种方案,枚举c 
49     if (a) {
50         dfs_c(u, a, 0); //u个数了,a的值为a,c的值为0 
51     }
52     //枚举当前这一位可以用哪个数字
53     for (int i = 1; i <= 9; i++) {
54         if (!st[i]) {
55             st[i] = true;
56             dfs_a(u + 1, a * 10 + i);
57             st[i] = false; //回溯恢复现场 
58         }
59     } 
60 }
61 int main() {
62     cin >> n;
63     dfs_a(0, 0); //一个数都没有, a = 0 
64     cout << ans << endl; 
65     return 0;
66 }

 

以上是关于AcWing 带分数 dfs的主要内容,如果未能解决你的问题,请参考以下文章

AcWing 842. 排列数字(DFS)

AcWing 1929. 镜子田地 dfs+异或+反证

AcWing 2060. 奶牛选美(DFS)

AcWing 842. 排列数字 DFS

ACwing92 递归实现指数型枚举 dfs

AcWing 2005. 马蹄铁(DFS)