【问题标题】:SIGSEGV Error in Simple Dynamic Programming on SPOJSPOJ 上的简单动态规划中的 SIGSEGV 错误
【发布时间】:2015-12-08 18:59:24
【问题描述】:

我刚开始学习动态编程,我刚刚尝试了一个基于 DP 的简单问题,在 Spoj 上。链接-http://www.spoj.com/problems/MST1/

这是问题陈述 -

对一个正整数,您可以执行以下 3 项中的任何一项 步骤。

1.) 减去 1。 (n = n - 1)

2.) 如果它可以被 2 整除,则除以 2。(如果 n % 2 == 0 ,则 n = n / 2)

3.) 如果它可以被 3 整除,则除以 3。(如果 n % 3 == 0 ,则 n = n / 3)

给定一个正整数 n,你的任务是找到最小的 n 到 1 的步骤。

输入:

输入包含整数 T (1 ≤ T ≤ 100) 个测试用例。 第二行输入是 N (0

输出:

对于每个案例,打印案例编号和最小步骤。

这是我的代码 -

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

// Memo Function returns the smallest number of steps possible for integer a

int memo(int a, int mem[]);

int mem[20000010];

int main() {
    int t;
    scanf("%i", &t);
    for(int i = 1; i <= t; i++) {
        int n;
        scanf("%i", &n);
        memset(mem, -1, sizeof(mem));
        mem[1] = 0;
        printf("Case %i: %i\n", i, memo(n, mem));   
    }
    return 0;
}

int memo(int a, int mem[]) {
    if (mem[a] != -1) return mem[a]; // If the value of smallest steps have already been calculated
    int r; // Current Lowest number of steps
    r = memo(a - 1, mem) + 1;
    if (a % 2 == 0) r = min(r, memo(a/2, mem) + 1);
    if (a % 3 == 0) r = min(r, memo(a/3, mem) + 1);
    mem[a] = r;
    return r;
}

我在 Internet 和 StackOverflow 上查找了此错误,我发现当我们尝试访问尚未分配的内存时可能会发生此错误,例如访问 10 元素数组的第 11 个元素.但我认为情况并非如此。

另外,我认为问题的上限是 2*10^7,数组也是全局的,所以应该不是问题。也许我使用 memset 函数的方式存在一些问题?我真的不知道!

任何帮助将不胜感激!感谢阅读!

【问题讨论】:

    标签: c++ segmentation-fault


    【解决方案1】:

    您的 DP 想法是正确的,但您的代码不适用于大输入(例如 1x10^6,或上限,2x10^7)。

    稍微修改一下代码,就可以预先计算出每一个答案,然后只输出你感兴趣的答案。由于问题的动态编程方式,即复杂的问题,这不会很耗时问题可以作为一个或多个先前解决的问题的组合来解决。

    int main() 
    {
        // Initialize DP array
        memset(mem, -1, sizeof(mem));
        mem[1] = 0;
    
        // Pre-compute every possible answer
        for(int i = 2; i <= 20000000; i++)
            mem[i] = memo(i);
    
        // Read the number of test cases
        int t;
        scanf("%d", &t);
    
        // Print only the desired answer, ie, mem[n]
        for(int i = 1; i <= t; i++) {
            int n;
            scanf("%d", &n);
            printf("Case %d: %d\n", i, mem[n]);
        }
    
        return 0;
    }
    

    我接受了这种方法。

    另一个提示:由于您的 DP 数组是全局的,您不必每次都将它传递给 DP 函数。

    【讨论】:

    • 非常感谢,马塞洛!据我了解,这里我们使用的是自下而上的方法,对吧?在我的代码中,我们从上到下计算数组中的解决方案。虽然这个解决方案肯定更干净,但我不明白的是为什么我的解决方案不起作用?不过,再次感谢!我欠你一个!
    猜你喜欢
    • 2011-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-22
    • 1970-01-01
    • 2013-08-09
    • 2014-08-08
    • 1970-01-01
    相关资源
    最近更新 更多