如何识别我的Alphacode实现中的错误?

时间:2015-12-30 09:33:39

标签: c dynamic-programming

以下是我对问题的实施: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上运行时,它显示“超出时间限制”。请帮助我找出错误。

2 个答案:

答案 0 :(得分:3)

有几个错误:

  • 您只为最后一个字符串打印一次结果。当然,您应该打印所有字符串的结果。您的代码目前看起来像这样:

    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 > 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;
}

答案 1 :(得分: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;
}