代码在C ++中进行动态编程的错误结果

时间:2014-10-14 17:20:30

标签: c++ dynamic-programming

我正在解决一个dp问题。问题是我有N个骰子;他们每个人都有K面,编号从1到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;
}

2 个答案:

答案 0 :(得分:0)

您使用dp的错误下标。

考虑有多少种方法可以获得800个骰子,每个骰子的数量从1到800, 如果在第一个骰子上将数字1设为最高,则得到总和10000 并且你在第二个骰子上最上面4个。

现在考虑如果你在第一个骰子上做2个最高点,有多少种方法可以得到10000 在第二个模具上最上面3个。

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

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

答案 1 :(得分:0)

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

  

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

注意它没有说“常数无符号长long c”。

你在相同的范围内定义了值k和K,这是令人愤怒的。

你硬编码1001和-1而不是给它们正确的软编码变量名。

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

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

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

空格键是你的朋友,写作抄袭者,ha vet ad。。。。。。。。。