【问题标题】:How to identify the bug in my Alphacode implementation?如何识别我的 Alphacode 实现中的错误?
【发布时间】:2015-12-30 09:33:39
【问题描述】:

以下是我对问题的实现:http://www.spoj.com/problems/ACODE/

#include <stdio.h>
#include <string.h>
int main() {
    long long int dp[5010] = { 0 }, i, len, ans;
    char str[5010];

    scanf("%s", str);
    while (str[0] != '0') {
       len = strlen(str);
       dp[0]  =1;
       for (i = 1; i < len; i++) {
           ans = (str[i-1] * 10 + str[i]);
           if (str[i] - '0')
               dp[i] = str[i];
           if (ans >= 10 && ans <= 26) {
                if ((i - 2) < 0)
                    dp[i] += dp[0];
                else
                    dp[i] += dp[i-2];
            }
        }
        scanf("%s", str);
    }
    printf("%llu\n", dp[len-1]);
    return 0;
}

当我在我的 IDE 中运行它时,它会被执行,但输出与预期完全不同。此外,当我在 Ideone 上运行它时,它会显示“超出时间限制”。请帮我找出我的错误。

【问题讨论】:

  • ans=(str[i-1]*10+str[i]); 可能不会像你想的那样做;你在这里操作 ASCII 码。您还应该打印每个字符串的结果,即在循环内。请根据作业要求在结果后打印一个换行符。
  • @MOehm 你建议我应该在循环内写什么?

标签: c dynamic-programming


【解决方案1】:

有几个错误:

  • 对于最后一个字符串,您只打印一次结果。当然,您应该打印所有字符串的结果。您的代码目前如下所示:

    scanf("%s",str);
    while (str[0] != '0') {
        // determine solution
    
        scanf("%s", str);
    }
    printf("%llu\n", dp[len-1]);
    

    printf 应该放在最后一个 scanf 之前。

  • 这个:

    ans = (str[i - 1] * 10 + str[i]);
    

    是对 ASCII 码的计算。你需要这样的东西:

    ans = ((str[i - 1] - '0') * 10 + str[i] - '0');
    
  • 代码

    if (str[i] - '0') dp[i] = str[i];
    

    应该处理以零开头的子字符串,但它使dp[i] 对于此类字符串有效地未初始化(或填充来自前一个字符串的垃圾)。

不过,主要的错误是您从错误的角度解决问题。当你通过字符串前进时,你的算法看起来像这样:

if the next two digits are a number from 10 to 26:
    dp[i] = dp[i + 1] + dp[i + 2]
else if the current digit isn't zero:
    dp[i] = dp[i + 1]
else:
    dp[i] = 0

该代码需要知道dp[j]j &gt; i 才能计算dp[i]。这意味着您可以通过向后遍历数组来解决问题。那么你的解决方案就是dp[0]

因为你只向前看一位或两位数,你甚至不需要辅助数组;保留最后两个值并在每次迭代后相应地交换它们就足够了。

这是一个解决方案。它仅针对给定的案例进行了测试,但它应该让您了解如何解决您的问题。代码没有做很多检查;假设字符串只有数字。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

unsigned long long poss(const char *str)
{
    unsigned long long p1, p2;
    size_t len = strlen(str);
    size_t i;

    if (len == 0) return 0;

    i = len - 1;
    p1 = 1;
    p2 = 1;

    if (str[i] == '0') p1 = 0;

    while (i-- > 0) {
        unsigned long long p = p1;

        if (str[i] == '0') p = 0;
        if (str[i] == '1') p += p2;
        if (str[i] == '2' && str[i + 1] < '7') p += p2;

        p2 = p1;
        p1 = p;
    }    

    return p1;
}

int main(void)
{
    char str[5001];

    while(scanf("%s",str) == 1 && str[0] != '0') {
        printf("%llu\n", poss(str));
    }

    return 0;
}

【讨论】:

    【解决方案2】:

    你需要的是一个递归函数,如果你发现 10 到 26 之间的东西,它会除法

    long long int count_decodings( const char * str )
    {
        long long int count = 1;
    
        // only accept digits 
        // continue while next character greater or equal '0' and less or equal '9'
        while ( ( *str >= '0' && *str <= '9' ) )
        {
            char actChar = *str;
            str ++; // increment string pointer ( now str points to character after actChar )
    
            if ( actChar == '1' && ( *str >= '0' && *str <= '9' ) )
            {
                // if we have 1 followed by somthing from 0 to 9 we have an new case
                count += count_decodings( str + 1 ); // continue with next sign and increment count of decodings
            }
            else if ( actChar == '2' && ( *str >= '0' && *str <= '6' ) )
            {
                // if we have 2 followed by somthing from 0 to 6 we have an new case
                count += count_decodings( str + 1 ); // continue with next sign and increment count of decodings
            }
        }
    
        return count;
    }
    
    int main()
    {
        char str[5010];
        scanf("%s",str);
        while(str[0]!=0)
        {
            long long int count = count_decodings( str );
            printf( "%llu\n", count);
            scanf("%s", str);
        }
        return 0;
    }
    

    【讨论】:

    • 虽然递归解决方案很优雅,但您可能应该提供某种记忆,以免一遍又一遍地重新计算相同的分支。尝试使用包含全部 1 或 2 的更长字符串的代码。
    • @MOehm 是的,当然!..谢谢!
    猜你喜欢
    • 2013-07-06
    • 1970-01-01
    • 2014-11-29
    • 1970-01-01
    • 2015-07-02
    • 2023-03-25
    • 1970-01-01
    • 2016-11-16
    • 1970-01-01
    相关资源
    最近更新 更多