AcWing 1209. 带分数

原题链接

考察:dfs

日常感慨自己的rz,自己想的思路和y总一样,也是dfs嵌套.但是代码不会实现而且想的是4个dfs嵌套.醉了

自己的思路:

       N = a+b/c,a b c的位数需要dfs枚举,确定位数后dfs a,b,c在最后c进行ans++.思路是4个嵌套但是不会剪枝555.而且感觉真的是极其复杂

暴力思路:

       完全没必要枚举位数.9个数字不能重复,相当于a,b,c在9个数字里各取数字.我们可以将9个数字铺展开.设置两个隔板.前面的为a,中间b,最后c.那么需要变动的不是a,b,c而是9个数字的顺序.直接用STL的全排列即可

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 using namespace std;
 6 typedef long long ll;
 7 const int N = 11;
 8 int a[N];
 9 ll calc(int st,int ed)
10 {
11     ll res = 0;
12     for(int i=st;i<=ed;i++)
13         res = res*10+a[i];
14     return res;
15 }
16 int main()
17 {
18     int ans = 0,n;
19     scanf("%d",&n);
20     for(int i=1;i<10;i++) a[i] = i;
21     do{
22         ll x,y,z;
23         for(int i=1;i<8;i++)
24         {
25             x = calc(1,i);
26             if(x>n) continue;
27             for(int j=i+1;j<9;j++)
28             {
29                 y = calc(i+1,j);
30                 z = calc(j+1,9);
31                 if(y/z>n) continue; 
32                 if(y%z!=0) continue;
33                 if(x+y/z==n) ans++;
34             }
35         }
36     }while(next_permutation(a+1,a+10));
37     printf("%d\n",ans);
38     return 0;
39 }
暴力全排列

Y总思路:

      dfs嵌套,但同样没必要枚举位数,直接枚举a,c.这是在暴力的行为上进行优化.因为b/c存在小数.所以等式两边*c,这样假设已经枚举了a,c.那么b就已知了: b = n*c-a*c

因此直接dfs枚举a与c即可.在dfs完a后再dfs c,在枚举每一个c的时候判断即可

dfs嵌套一定要分清哪些部分是枚举,哪些部分是继续dfs,哪些部分是判断是否回溯.

判断是否回溯不一定要和继续dfs(或者检验答案)写在一起

坑点:

      n*c可能溢出

     b要判断是否为0

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 typedef long long ll;
 7 const int N = 13;
 8 int n,ans;
 9 bool st[N],backup[N];
10 bool check(int a,int c)
11 {
12     ll b = (ll)c*n-(ll)a*c;
13     if(!b) return false;
14     memcpy(backup,st,sizeof st);
15     while(b)
16     {
17         if(b%10==0||backup[b%10]) return false;
18         backup[b%10] = 1;
19         b/=10;
20     }
21     for(int i=1;i<=9;i++) if(!backup[i]) return false;
22     return true;
23 }
24 void dfs_c(int k,int a,int c)
25 {
26     if(k==n) return;//递归终止条件
27     if(c&&check(a,c)) ans++; 
28     for(int i=1;i<=9;i++)//枚举C
29     {
30         if(!st[i])
31         {
32             st[i] = 1;
33             dfs_c(k+1,a,c*10+i);
34             st[i] = 0;
35         }
36     }
37 }
38 void dfs_a(int k,int now)
39 {
40     if(now>n||k==n) return;
41     if(now) dfs_c(k,now,0);//用了几个数字,a,c
42     for(int i=1;i<=9;i++)//for循环里是枚举a
43     {
44         if(!st[i])
45         {
46             st[i] = 1;
47             dfs_a(k+1,now*10+i);//枚举每一个a
48             st[i] = 0;
49         }
50     }
51 }
52 int main()
53 {
54     scanf("%d",&n);
55     dfs_a(0,0);
56     printf("%d\n",ans);
57     return 0;
58 }
优化

 

posted @ 2021-01-18 16:29  acmloser  阅读(70)  评论(0编辑  收藏  举报