Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 换硬币,只要能';我没弄对_C#_Algorithm_Coin Change - Fatal编程技术网

C# 换硬币,只要能';我没弄对

C# 换硬币,只要能';我没弄对,c#,algorithm,coin-change,C#,Algorithm,Coin Change,您好,我正在尝试创建一个算法,找出有多少种方法可以让我的变化回来。 但我就是不能正确地执行,我一直得到4分,而我应该得到6分,我就是不明白为什么 这是我在C#中的实现,它是从 private static int[]S={1,2,5}; 私有静态void Main(字符串[]args) { 整数金额=7; 整数方式=计数2(数量,S.长度); Console.WriteLine(“对“+amount+”kr:+Ways.ToString()进行更改的方法”); Console.ReadLine(

您好,我正在尝试创建一个算法,找出有多少种方法可以让我的变化回来。 但我就是不能正确地执行,我一直得到4分,而我应该得到6分,我就是不明白为什么

这是我在C#中的实现,它是从

private static int[]S={1,2,5};
私有静态void Main(字符串[]args)
{
整数金额=7;
整数方式=计数2(数量,S.长度);
Console.WriteLine(“对“+amount+”kr:+Ways.ToString()进行更改的方法”);
Console.ReadLine();
}    
静态整数计数2(整数n,整数m)
{
int[,]表=新的int[n,m];
对于(int i=0;i//2:塔尔贝[i如果你解释一下你的算法应该是如何工作的,那会很有用。如果没有注释,变量的名称只是
n
m
i
,那么很难理解它的用途。在迭代各种类型的硬币时,你应该使用更具描述性的名称,例如
coinType
例如

然而,有些地方对我来说似乎很可疑。例如,变量
i
j
迭代范围
1..m
1..n
中的值-它们始终是正值。这意味着规则2和规则3永远无法运行:

// ...
  else if (i <= -1)     // <- can never be 'true'
    total += 0; 
  else if (j - 1 <= -1) // <- 'true' when 'j == 0'
// ...
  if (j - 1 <= -1)      // <- can never be 'true'
// ...
/。。。
如果(i0.05)有一些观察结果

1) 如果将
count
函数从伪代码移到单独的子例程中,会使代码更简单(并且更不容易出错)

在你的内心循环中


2) 在
count2
中,您的第一个循环将出现
n-1次。这意味着,对于
n==1
,您将不会进入循环体,也不会找到任何解决方案。对于内部循环也是如此:如果只有一个硬币,您将不会找到任何解决方案。

我相信您指的是表[I,j]只使用硬币{0,1,2,…,j-1}来存储实现精确1美分值的方法的数量

本质上,while循环的内部部分表示表[i,j]应等于不使用任何硬币j而达到i值的方式的数量,加上使用至少一个硬币S[j]来实现i值的方式的数量。因此,除了边界情况外,该值为表[i,j-1]+表[i-S[j],j];总和的第一部分是不使用价值S[j]的硬币达到i的方式的数量,第二部分是使用至少一个价值S[j]的硬币达到i的方式的数量

尝试更改:

        // second sub-problem
        // count(n-S[m], m)
        if (j - 1 <= -1) // rule 3
            total += 0;
        else if (i - S[j - 1] == 0) // rule 1
            total += 1;
        else if (i - S[j - 1] <= -1) // rule 2
            total += 0;
        else
            total += table[i - S[j-1], j];
//第二个子问题
//计数(n-S[m],m)

如果(j-1完全出于深夜的无聊(是的,这肯定需要改进)…它同时使用递归、linq和yield,并且有和代码行一样多的大括号,所以我非常喜欢它

    static IEnumerable<List<int>> GetChange(int target, IQueryable<int> coins)
    {
        var availableCoins = from c in coins where c <= target select c;
        if (!availableCoins.Any())
        {
            yield return new List<int>();
        }
        else
        {
            foreach (var thisCoin in availableCoins)
            {
                foreach (var result in GetChange(target - thisCoin, from c in availableCoins where c <= thisCoin select c))
                {
                    result.Add(thisCoin);
                    yield return result;
                }
            }
        }
    }
静态IEnumerable GetChange(int目标,IQueryable硬币)
{

var availableCoins=来自硬币中的c,其中c这是工作顺序中的算法。按绿色的“播放”箭头运行它。


我认为主要的问题是算法循环应该从-1开始。我认为递归编写会更清晰,但这是一个有趣的练习。

很抱歉,0..n和0..m是一个错误:D@DoomStone:即使
i
可能是
0
,那么仍然是
i这是真的,但它应该对结果没有影响。@DoomStone:是的,它是真的意思是一样的,但后者更容易理解。我仍然不理解代码背后的逻辑,我相信像这样的小改动(以及重命名和一些注释)真的会有帮助。我给你的代码中有一个错误,它是0..n和0..m。我已经在第一次修改了代码post@DoomStone听起来并不是很迂腐,但我真的认为在你的内部循环中去掉spagetti代码会帮助你找到一个bug。很抱歉,如果(j-1)应该是s[j-1],那么它应该是0..n和0..mIf因为S从0开始,转到m-1I,我认为你无论如何都不需要那个测试。请参见编辑。变量j永远不小于0。是的,每个i的j都是0,然后j-1=-1这就是为什么你需要将j-1更改为j。这很好,很简洁,而且你是对的,同时使用了各种技术。但是,如果给定的硬币没有解决方案,这是错误的结算的计算结果变化较小。例如,目标20,硬币3,6产生的组合相加到18。因此,使用这一方法只需检查结果相加到目标。实际上,由于这是将所有硬币循环到目标,因此这是正确和错误解的混合。例如,目标18加上6,5得到6665655655555。
table[i][j] = count(table, i, j - 1) + count(table, i - S[j], j)
        // second sub-problem
        // count(n-S[m], m)
        if (j - 1 <= -1) // rule 3
            total += 0;
        else if (i - S[j - 1] == 0) // rule 1
            total += 1;
        else if (i - S[j - 1] <= -1) // rule 2
            total += 0;
        else
            total += table[i - S[j-1], j];
        // second sub-problem
        // count(n-S[m], m)
        if (i - S[j] == 0) // rule 1
            total += 1;
        else if (i - S[j] < 0) // rule 2
            total += 0;
        else
            total += table[i - S[j], j];
    static IEnumerable<List<int>> GetChange(int target, IQueryable<int> coins)
    {
        var availableCoins = from c in coins where c <= target select c;
        if (!availableCoins.Any())
        {
            yield return new List<int>();
        }
        else
        {
            foreach (var thisCoin in availableCoins)
            {
                foreach (var result in GetChange(target - thisCoin, from c in availableCoins where c <= thisCoin select c))
                {
                    result.Add(thisCoin);
                    yield return result;
                }
            }
        }
    }