我遇到了一个数字动态编程问题。
让x是一个没有相邻数字的数字,使得abs(x[i] - x[i+1]) <= 1
,即,如果获取x任意两个相邻数字之差的绝对值,则得到的数字将大于1。例如,数字1和2不能相邻,数字5和5不能相邻。
目标是计算x在[A,B]范围内的数量。我知道这是一个digit dynamic programming问题,但我不知道我的尝试出了什么问题。
示例: 对于输入:110 130,输出应为1(因为只有130满足该条件)。我的代码正确输出1,但在其他输入上失败。
这是我的尝试。我知道我需要添加备忘录,但是我想在之前就得到算法。
#include <vector>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
using namespace std;
int dp[5001][10][2];
const int MOD = 10000;
int count(vector<int> &digits, int idx, int digit_before, int less, int leading_zero) {
if (idx == digits.size()) return 1;
if (dp[idx][digit_before][leading_zero] != -1 && less)
return dp[idx][digit_before][leading_zero];
int cnt = 0;
int k = less ? 9 : digits[idx];
for (int i = 0; i <= k; i++) {
int zero = (i == 0) ? leading_zero : 0;
int new_less = (i == k) ? less : 1;
if (!leading_zero && abs(digit_before - i) <= 1) continue;
cnt += count(digits, idx + 1, i, new_less, zero);
cnt %= MOD;
}
if (less) {
dp[idx][digit_before][leading_zero] = cnt;
}
return cnt;
}
int main() {
memset(dp, -1, sizeof(dp));
string a, b;
cin >> a >> b;
vector<int> a_digits{};
for (auto i = 0; i < a.size(); i++) {
a_digits.push_back(a[i] - '0');
}
vector<int> b_digits{};
for (auto i = 0; i < b.size(); i++) {
b_digits.push_back(b[i] - '0');
}
auto i = a_digits.size() - 1;
for (; a_digits[i] == 0; i--);
a_digits[i]--;
cout << (count(b_digits, 0, 0, 0, 1) - count(a_digits, 0, 0, 0, 1)) % MOD;
return 0;
}
答案 0 :(得分:0)
您的代码中有几个错误。例如:
// try for a_digits = {1,0,0,0};
auto i = a_digits.size() - 1;
for (; a_digits[i] == 0; i--);
a_digits[i]--;
您的dp[idx][digit_before][leading_zero]
状态不正确。应该是dp[idx][digit_before][leading_zero][less]
,因为int k = less ? 9 : digits[idx];
取决于less
。
另外,由于memset(dp, -1, sizeof(dp));
可能会有所不同,因此每次调用count(vector<int> &digits, int idx, int digit_before, int less, int leading_zero)
之前都必须设置vector<int> &digits
。
固定代码如下:
#include <vector>
#include <iostream>
#include <algorithm>
#include <string>
#include <string.h>
using namespace std;
int dp[5001][10][2][2];
const int MOD = 10000;
int count(vector<int> &digits, int idx, int digit_before, int less, int leading_zero) {
if (idx == digits.size()) return 1;
if (dp[idx][digit_before][leading_zero][less] != -1)
return dp[idx][digit_before][leading_zero][less];
int cnt = 0;
int k = less ? 9 : digits[idx];
for (int i = 0; i <= k; i++) {
int zero = (i == 0) ? leading_zero : 0;
int new_less = (i == k) ? less : 1;
if (!leading_zero && abs(digit_before - i) <= 1) continue;
cnt += count(digits, idx + 1, i, new_less, zero);
cnt %= MOD;
}
dp[idx][digit_before][leading_zero][less] = cnt;
return cnt;
}
int main() {
string a, b;
cin >> a >> b;
vector<int> a_digits{};
for (auto i = 0; i < a.size(); i++) {
a_digits.push_back(a[i] - '0');
}
vector<int> b_digits{};
for (auto i = 0; i < b.size(); i++) {
b_digits.push_back(b[i] - '0');
}
auto i = a_digits.size() - 1;
for (; a_digits[i] == 0; i--);
a_digits[i]--;
if(a_digits[i] == 0) {
i++;
for(; i <= a_digits.size(); i++) {
a_digits[i] = 9;
}
}
memset(dp, -1, sizeof(dp));
int cnt1 = count(b_digits, 0, 0, 0, 1);
memset(dp, -1, sizeof(dp));
int cnt2 = count(a_digits, 0, 0, 0, 1);
cout << ( cnt1 - cnt2 + MOD ) % MOD;
return 0;
}