题目:
题目理解和思路:
1.此题是给一个6位车牌号,正着不能含有连着的62,不能有4。
2.判断车牌号可能会采用dfs,因为每增加一位数就包含带4,或者形成62两种不合法情况(事实上没有用到)。
3.车牌的特性为,序号为的9车牌事实上相当于009。
解题步骤:
1.建立一个dp数组,对dp数组进行数据维护。第i行第j列表示以数字j开头长度为i的合法车牌数量(毫无疑问dp[x][4]全为0,dp[x][6]相对于其他列也应该会少)
具体维护方式(状态转移方程):dp[i][x]+=dp[i-1][k] (x==6&&k==2时不加,x==4时直接赋0值。其他情况皆为遍历0-9所有数字然后加和)
维护代码:
void Init() { /*预处理*/
for (int j = 0; j < maxsize; j++) {
dp[1][j] = 1;
}
dp[1][4] = 0;
for (int i = 2; i < maxsize; i++) {
for (int j = 0; j < maxsize; j++) {
if (j == 4) {
dp[i][j] = 0; continue;
}
for (int k = 0; k < maxsize; k++) {
if(!(j==6&&k==2))dp[i][j] += dp[i - 1][k];
}
}
}
}
维护后数组样式:
2.对输入的数据进行处理
判断某个数到1之间的所有合法车牌:
举例,若求1-384之间的合法车牌。应该包括
三位数:000-099,100-199,200-299
二位数的默认第一位为3
两位数:00-09 10-19 20-29 30-39 40-49 50-59 60-69 70-79
一位数的默认前两位为38
一位数:0-4
因此结果应该为dp[3][0]+dp[3][1]+dp[3][2]+dp[2][0]+..............+dp[2][7]+dp[1][1]+...........+dp[1][4]
计算函数:
int caculate(string s) {
int m=0;
for (int i = 0; i < s.length(); i++) { /*高位到低位*/
for (int j = 0; j < s[i] - 48; j++) {
if ((i != 0 && s[i - 1] == '6' && j == 2) || j == 4) {
continue;
}
else {
m += dp[s.length() - i][j];
}
}
if ((i != 0 && s[i - 1] == '6' && s[i] == '2') || s[i] == '4') {
m--; break;
}
}
return m;
}
3.此外值得注意的是,因为输入的是两个数据,理论来说应该由384所计算的dp数组和减1计算的dp数组和,但是在计算大的dp数组和时已经包括了1,所以在计算两者的dp和时1应该减1变成0。(和前缀和问题类似)
最终代码:
#include<iostream>
#include<string>
#define maxsize 10
using namespace std;
int dp[maxsize][maxsize] = { 0 };
void Init();
int caculate(string s);
string inttostring(int x1);
int main() {
Init();
//print();
int x1, x2;
string s1, s2;
while (true) {
cin >> x1 >> x2;
if (x1 == 0 && x2 == 0)break;
x1--; /*小的数要减1*/
s1 = inttostring(x1);
s2 = inttostring(x2);
cout << caculate(s2) - caculate(s1)<< endl;
}
return 0;
}
string inttostring(int x1) { /*整数变字符串方便处理*/
string s;
int cnt = 0;
int num[15];
while (x1) {
num[cnt] = x1 % 10;
x1 /= 10;
cnt++;
}
for (int i = cnt - 1; i >= 0; i--) {
s.push_back(num[i] + 48);
}
return s;
}
int caculate(string s) {
int m=0;
for (int i = 0; i < s.length(); i++) { /*高位到低位*/
for (int j = 0; j < s[i] - 48; j++) {
if ((i != 0 && s[i - 1] == '6' && j == 2) || j == 4) {
continue;
}
else {
m += dp[s.length() - i][j];
}
}
if ((i != 0 && s[i - 1] == '6' && s[i] == '2') || s[i] == '4') {
m--; break;
}
}
return m;
}
void Init() { /*预处理*/
for (int j = 0; j < maxsize; j++) {
dp[1][j] = 1;
}
dp[1][4] = 0;
for (int i = 2; i < maxsize; i++) {
for (int j = 0; j < maxsize; j++) {
if (j == 4) {
dp[i][j] = 0; continue;
}
for (int k = 0; k < maxsize; k++) {
if(!(j==6&&k==2))dp[i][j] += dp[i - 1][k];
}
}
}
}