产生数这道题是一道很好的训练BFS和DFS的题,由于我是一个萌新,且正在学习DFS(深度优先搜索),我便把我的DFS代码展示出来,以供各位萌新学习。如果各位大佬有更好的DFS做法,欢迎向我提出建议。

产生数
 

描述

 

给出一个整数n(n≤2000)和k个变换规则(k≤15)。规则:

① 1个数字可以变换成另1个数字;

② 规则中,右边的数字不能为零。

例如:n=234,k=2规则为

2 → 5

3 → 6

上面的整数234经过变换后可能产生出的整数为(包括原数)234,534,264,564共4种不同的产生数。

求经过任意次的变换(0次或多次),能产生出多少个不同的整数。仅要求输出不同整数个数。

 

输入

n

k

x1 y1

x2 y2

... ...

xn yn

输出

输出满足条件的整数个数。

输入样例 1 

234
2
2 5
3 6

输出样例1

4

 

 

首先,我们要知道一个数学公式:满足条件的个数之和=(每位数字的可变化次数+1)相乘;

如234,1,2->5;则个位数字的可变化次数=0,十位数字的可变化次数=0,百位数字的可变化次数=1;所以满足条件的个数之和=(0+1)*(0+1)*(1+1)=2;

懂得了这一点,这道题就基本上完成了一半了,然后就是写代码:

这是我最先的代码:

这种做法爆了3个点,经过我思考后,对代码进行了一些修改,如下:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 int a[15],b[15],c[4],error[10];
  4 //a,b分别为规则中x1,y1,c为n的各位数字,error为统计重复出现的数字
  5 int n,m,tot,tmp,ans=1;
  6 //n为最初的三位数,m为规则个数,tot统计每位可变化次数,tmp用来统计无效位数,ans用来记录答案
  7 //void f(int p)
  8 //{
  9 //    for(int j=0;j<m;j++)//从每个规则中寻找符合的
 10 //    {
 11 //        if(p==a[j])
 12 //        {
 13 //            tot++;
 14 //            if(error[p]!=0)//避免无限调用f函数,如果重复则不调用
 15 //            {
 16 //                for(int i=0;i<9;i++)
 17 //                {
 18 //                    if(error[i]!=0)
 19 //                    {
 20 //                        tot--;
 21 //                        error[i]=0;//清空数组
 22 //                    }
 23 //                }
 24 //            }
 25 //            else
 26 //            {
 27 //                error[p]=p;//统计重复出现
 28 //                f(b[j]);//递归调用
 29 //            }
 30 //        }
 31 //    }
 32 //}
 33 //void dfs()
 34 //{
 35 //    for(int i=0;i<(4-tmp);i++)
 36 //    {
 37 //        f(c[i]);//调用f函数查找某位数数字的可变化次数
 38 //        ans=ans*(tot+1);//满足条件的个数之和
 39 //        tot=0;//清除当前位数的统计信息,为统计下一位做铺垫
 40 //    } 
 41 //}
 42 //int main()
 43 //{
 44 //    cin>>n>>m;//输入
 45 //    for(int i=0,j=1000;i<4;i++,j/=10)
 46 //    {
 47 //        if(tmp==i&&n/j==0)//统计无效位数
 48 //        {
 49 //            tmp++;
 50 //        }
 51 //        else
 52 //        {
 53 //            c[i-tmp]=n/j%10;//提取各个位数上的数字
 54 //        }
 55 //    }
 56 //    for(int i=0;i<m;i++)
 57 //    {
 58 //        cin>>a[i]>>b[i];//输入
 59 //    }
 60 //    dfs();//调用
 61 //    cout<<ans;
 62 //    return 0;
 63 //}
 64 void dfs(int p)
 65 {
 66     error[p] = 1;//打标记 
 67     tot++;//相当于最后的+1
 68     for(int j = 0; j < m; j++)//从每个规则中寻找符合的
 69     {
 70         if(a[j]==p)
 71         {
 72             if(error[b[j]]==0)//避免无限调用f函数,如果重复则不调用
 73             {
 74                 f(b[j]);
 75             }
 76         }
 77     }
 78 }
 79 int main()
 80 {
 81     cin>>n>>m;
 82     for(int i=0,j=1000;i<4;i++,j/=10)
 83     {
 84         if(tmp==i&&n/j==0)
 85         {
 86             tmp++;//统计无效位数
 87         }
 88         else
 89         {
 90             c[i-tmp]=n/j%10;//提取各个位数上的数字
 91         }
 92     }
 93     for(int i=0;i<m;i++)
 94     {
 95         cin>>a[i]>>b[i];
 96     }
 97     for(int i=0;i<(4-tmp);i++)
 98     {
 99         dfs(c[i]);
100         ans *= tot;
101         // 当前位清理统计信息,为下一次统计做准备 
102         tot=0;
103         for(int j = 0; j <= 9; j++) error[j] = 0;//清空数组
104     }
105     cout<<ans;
106     return 0;
107 }

这是我老师的做法,思路相同,但写法不一样:

其中作用是把vis数组清空,作用详见https://www.csdn.net/gather_27/MtjakgwsNzYtYmxvZwO0O0OO0O0O.html

posted on 2020-02-07 18:31  blcym  阅读(605)  评论(0编辑  收藏  举报