【发布时间】:2018-09-02 19:31:07
【问题描述】:
我创建了一个 DP 程序,但问题是当我不使用 memoization 时我得到了正确的答案。一旦我引入记忆化,我就开始对一些问题得到错误的答案
这是关闭记忆功能的 C++ 14 中的代码(通过评论)
#include <iostream>
#include <math.h>
#include<algorithm>
using namespace std;
int max_Number_of_turns;
int dp[9999][1000];
int changeTheDigit(int n, int d) {
int rem = n % (int) (pow(10, 4 - d));
n /= (pow(10, 4 - d));
int x = n % 10;
n /= 10;
if (x == 9) x = 0;
else x = x + 1;
n = n * (10) + x;
n = n * (pow(10, 4 - d)) + rem;
return n;
}
int minMax(int n, int t) {
int ans =0;
//if(dp[n][t]>=0) { return dp[n][t];}
if (t > max_Number_of_turns) return n;
int N;
for (int i = 0; i < 4; i++) {
N = changeTheDigit(n, i + 1);
if (t % 2 == 0) {
//Manish chance
if(ans==0) ans=minMax(N, t+1);
else ans = min(ans, minMax(N, t + 1));
} else {
//Nitish Chance
ans = max(ans, minMax(N, t + 1));
}
}
//cout << ans << endl;
dp[n][t]=ans;
return ans;
}
using namespace std;
int main() {
int T, N, M;
cin >> T;
while (T--) {
cin >> N >> M;
max_Number_of_turns=M;
for(int i=0;i<9999;i++)
for(int j=0;j<1000;j++)
dp[i][j]=-1;
if(minMax(N,1)>N){
cout << "Nitish" << endl;
}
else{
cout << "Manish" << endl;
}
}
return 0;
}
打开记忆注释(即从该行中删除 cmets)
if(dp[n][t]>=0) { return dp[n][t];}
我的代码会对一些问题给出错误的答案 例如,让我们考虑输入
1
4569 12
原始正确的解决方案是 Manish 但是如果我打开 memoization,我的解决方案是 Nitish
你能告诉我我在这里做错了什么
另外,一个有趣的事实是,如果将 DP 代码从
if(dp[n][t]>=0) { return dp[n][t];}
到
if(dp[n][t]>0) { return dp[n][t];}
然后一切都很好
【问题讨论】:
-
"我一介绍 DP,就开始对一些问题得到错误的答案" - 也许你实现不正确?
-
为什么不采用该代码并使用您的调试器?此代码是否来自您使用其嵌入式编译器的“在线编码”站点之一,而不是获取您自己的编译器以便您可以调试代码?如果是这样,请获取一个编译器,获取您的代码,编译它,调试它。你有测试用例和它产生的输出——不需要我们为你做调试工作。
-
minMax偶尔会与n >= 9999一起调用,因此dp会被越界访问,并且程序会表现出未定义的行为。 -
@VishalSingh 为了证明 Igor Tandetnik 所说的,see this。
std::vector和at()的使用表明你正在越界。这表明在线编码网站没有教如何诊断问题,甚至没有编写可以轻松诊断问题的 C++ 代码。如果您不使用原始数组而是使用std::vector,您将有机会自己轻松找到问题。 -
@VishalSingh No it doesn't run at all。问题是您使用的是原始数组,如果您越界,则不能保证会发生任何“坏事”,但您永远不会知道您越界了。如果您使用了
std::vector,则保证如果您使用at()而不是[]访问越界元素,则会引发异常。当您真正知道如何编写良好的 C++ 代码,或者至少知道如何编写能够揭示错误的代码时,您会发现其中的区别吗?错误只会暴露自己。在线编码网站并不强调这一点。
标签: c++ recursion dynamic c++14 memoization