dfs写法模板总结
参考博客
必写:
pos: 表示数字的位数
从末位或第一位开始,要根据题目的数字构造性质来选择顺序,一般选择从 a1 到 an 的顺序。初始从 len 开始的话,边界条件应该是 pos=0,限制位数应该是 apos, DFS时 pos−1 ;初始从1 开始的话,边界条件应该是 pos>len,限制位数应该是 alen−pos+1 , DFS时 pos+1 。两种都可以,看个人习惯。
可选参数:
pre:表示上一个数是多少
有些题目会用到前面的数
lead: 前导零是否存在,lead=1 存在前导零,否则不存在。
一般来说有些题目不加限制前导零会影响数字结构,所以 lead 是一个很重要的参数。
如果 lead=1 且当前位为 0 ,那么说明当前位是前导 0,继续搜索 pos+1,其他条件不变。
如果 lead=1 且当前位不为 00,那么说明当前位是最高位,继续搜索 pos+1,条件变动。
如果 lead=0,则不需要操作。
sum : 搜索到当前所有数字之和
有些题目会出现数字之和的条件
cnt: 某个数字出现的次数
cnt: 某个数字出现的次数 有些题目会出现某个数字出现次数的条件
limit: 可以填数的限制
可以填数的限制(无限制的话(limit=0) 0∼9 随便填,否则只能填到 ai)
不要62
题意: 找到区间 [L,R][L,R]
不能出现 4 和 62 的数的个数
分析: 首先此题不需要 lead,其次有 62 所以要记前驱 pre
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
#include <bits/stdc++.h>
using namespace std;
const int N = 15;
int l, r, dp[N][N], len, a[N];
int dfs(int pos, int pre, int limit) {
if (!pos) return 1;
if (!limit && dp[pos][pre] != -1) return dp[pos][pre];
int res = 0, up = limit ? a[pos] : 9;
for (int i = 0; i <= up; i ++) {
if (i == 4 || (i == 2 && pre == 6)) continue;
res += dfs(pos - 1, i, limit && i == up);
}
return limit ? res : dp[pos][pre] = res;
}
int cal(int x) {
memset(dp, -1, sizeof dp);
len = 0;
while (x) a[++ len] = x % 10, x /= 10;
return dfs(len, 0, 1);
}
signed main() {
while (cin >> l >> r, l || r) {
cout << cal(r) - cal(l - 1) << endl;
}
}
|
题目6:计数问题
题意: 统计区间[L,R]
出现 0123456789的各个数字总次数
分析: 需要用到 lead,需要用到次数总和 sum,还有哪个数字 num。基本上可以套模板,注意边界条件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
#include <bits/stdc++.h>
using namespace std;
const int N = 15;
int l, r, len, a[N], dp[N][N];
int dfs(int pos, int sum, int num, int lead, int limit) {
if (!pos) {
if (lead && !num) return 1;
return sum;
}
if (!limit && !lead && dp[pos][sum] != -1) return dp[pos][sum];
int res = 0, up = limit ? a[pos] : 9;
for (int i = 0; i <= up; i ++) {
int t;
if (i == num) {
if (!num) {
t = sum + (lead == 0);
} else {
t = sum + 1;
}
} else {
t = sum;
}
res += dfs(pos - 1, t, num, lead && i == 0, limit && i == up);
}
return limit ? res : (lead ? res : dp[pos][sum] = res);
}
int cal(int x, int num) {
memset(dp, -1, sizeof dp);
len = 0;
while (x) a[++ len] = x % 10, x /= 10;
return dfs(len, 0, num, 1, 1);
}
signed main() {
while (cin >> l >> r, l || r) {
if (l > r) swap(l, r);
for (int i = 0; i <= 9; i ++) cout << cal(r, i) - cal(l - 1, i) << " ";
cout << endl;
}
}
|