【问题标题】:Wrong result for code doing dynamic programming in C++在 C++ 中进行动态编程的代码的错误结果
【发布时间】:2014-10-14 17:20:29
【问题描述】:

我正在解决一个 dp 问题。问题是我有 N 个骰子;他们每个人都有从 1 到 K 编号的 K 个面。现在我将 N 个骰子排成一行。如果我愿意,我可以旋转/翻转任何骰子。有多少种方法可以设置顶面,使所有顶面的总和等于 S?

现在给了我 N、K、S;我必须计算方法的总数。值得一提的是,我必须打印模 100000007 的结果。我试图解决这个问题并为此编写代码,但我的代码不适用于这种情况:800 800 10000 为什么?我不明白。谁能解释我的代码不起作用的原因。我的代码在这里:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<memory.h>
#define M 100000007
#define ull unsigned long long
using namespace std;
ull n,K,s,dp[1001][1001];
ull fnc(int num,int sum,int k)
{
   ull temp;
   if(num==0){
     if(sum==0) return 1;
     else return 0;
   }
   if(dp[num][k]!=-1)
   return dp[num][k];
   for(int i=1;i<=K;i++)
   {
       temp=temp%M+fnc(num-1,sum-i,i)%M;
   }
   return dp[num][k]=temp%M;
}
int main()
{
    int T;
    cin>>T;
    for(int t=1;t<=T;t++)
    {
      cin>>n>>K>>s;
      memset(dp,-1,sizeof(dp));
      printf("Case %d: %lld\n",t,fnc(n,s,0));
    }
    return 0;
}

【问题讨论】:

  • 你能用伪代码替换你的 C++ 代码吗?不是每个人都懂 C++,而且 C++ 也相当冗长。还要解释一下表格中每个单元格的含义dp
  • for dp[n][k] n 表示投掷次数,k 表示骰子的面值。
  • dp[n][k] 应该包含什么?此外,所有这些都应该作为问题的一部分出现。
  • @YuvalFilmus 完全不清楚问题出在算法上,而不是实现上,因此伪代码可能无法解决问题。 (OTOH,将算法转换为伪代码可能会帮助提问者找出问题所在。)但是,无论如何,“请修复我的代码”在 CS.SE 上是题外话。如果添加了对代码预期行为的解释,那么它在Stack Overflow 上是合理的主题。
  • @YuvalFilmus 不,你不能。使用原始 C++ 中的代码,可能会发现算法和实现中的错误;在伪代码中使用它,只能找到算法中的错误。 (请注意,这一系列 cmets 来自 Computer Science SE 上帖子的原始位置。显然,Yuval 不会建议在 SO 上用伪代码替换代码。)

标签: c++ dynamic-programming


【解决方案1】:

dp 使用了错误的下标。

考虑一下有多少种方法可以获得 800 个骰子,每个骰子的数字从 1 到 800, 如果您在第一个骰子上将数字 1 放在最上面,则总和为 10000 然后你在第二个骰子上打出 4。

现在考虑一下,如果你在第一个骰子上将 2 放在最上面,有多少种方法可以得到总和 10000 和 3 在第二个骰子的最上面。

这两个数量是相同的:每个都是让 798 个骰子(数字从 1 到 800)得到总和为 99995 的方式数。是你想要记住的数量类型. 但是您甚至没有在dp 中分配足够的空间来存储这种部分答案。

我还想知道为什么你使用unsigned long long 而不仅仅是unsigned long,因为你的答案是模100000007。你永远不必 使用甚至接近 signed long 最大值的数字。

【讨论】:

    【解决方案2】:

    根据http://linux.die.net/man/3/memset

    memset() 函数用常量字节 c 填充 s 指向的内存区域的前 n 个字节。

    注意它没有说“常量 unsigned long long c”。

    你把值 k 和 K 定义在同一个作用域中,这很气人。

    您对 1001 和 -1 进行了硬编码,而不是为它们提供正确的软编码变量名称。

    您的大多数变量名称都是 1 个字符长。

    您在 return 语句中有持久的行为。

    您绝对无法检查 k、K 和 num 的值是否在 dp 的适当范围内,这部分是硬编码 1001 的结果。

    空格键是你的朋友,写这样的代码,我们必须准备好讨厌。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多