【问题标题】:Every possible combination of X split into N stacksX 的每个可能组合都分成 N 个堆栈
【发布时间】:2012-06-13 16:48:58
【问题描述】:

我确信这个问题有一个正式的名称,知道这个名称可能会帮助我找到解决方案,但我不知道,并且为 Google 提出问题的措辞一直将我指向Knapsack Problem,它是不是一回事。

我想取一些值 X 并找到将该值拆分为 N 个整数堆栈的所有可能组合。

如果我的措辞令人困惑,这里是 X = 4,N = 3 的示例

Stack -> 1 | 2 | 3 |
----------------------
#1-----> 4 | 0 | 0 |
----------------------
#2-----> 3 | 1 | 0 |
----------------------
#3-----> 2 | 1 | 1 |
----------------------
#4-----> 2 | 2 | 0 |

重复是可以接受的,因为它很容易删除,但理想情况下它不会被计算。解决问题的算法将是完美的,但即使找出问题的名称也会使研究更容易。谢谢。

【问题讨论】:

  • 那么,您希望n 的数字加起来正好是x 的总和?您不希望包含少于n 部分的组合/排列吗?零是有效部分。零件的顺序重要吗?不同顺序的相同部分会重复吗?
  • 您只需要组合的数量,还是要打印所有组合?
  • 我认为这可能与您正在寻找的相似。 stackoverflow.com/questions/2593781/…
  • 如果你再想一想,这实际上是 NP 背包问题。我认为,只是您的 sack 中包含小于 x 且大于 0 的所有整数,并且您只需要 n 长度的组合。
  • @Jodrell 是的,n 的数字正好加到 x

标签: c# algorithm math combinatorics


【解决方案1】:

这些其实都是integer partitions作为已删除答案的备注。使用Mathematica

IntegerPartitions[4, 3] // PadRight //Grid

输出:

4   0   0
3   1   0
2   2   0
2   1   1

我找不到 C# 实现,但这里有几个相关的问题:

Elegant Python code for Integer Partitioning

Integer Partition in Java

Algorithm for generating integer partitions


谷歌点击:

Integer Partition Algorithm by Jerome Kelleher

Integer Partition Algorithm by Daniel Scocco

Fast Algorithms for Generating Integer Partitions (PDF)(看起来很重)

Stony Brook Algorithm Repository - Partitions

【讨论】:

  • @MrWizard 谢谢你的名字,这会有所帮助。我有兴趣知道这是如何产生的。这些链接中似乎没有任何代码显示正在使用的算法。
  • @MrWizard,发布得太早了,感谢您提供代码链接!
  • @Tyrsius 我会在找到它们后添加更多内容,请继续关注。
  • 那太好了,等我把一个c#方法放在一起我就贴出来。
  • @Tyrsius 我又找到了一个我想加入的链接;它链接到几个不同的实现并给它们评级。
【解决方案2】:

这似乎可以解决问题:

vector<vector<int> > partitions(int X, int N, int Y)
{
    vector<vector<int> > v;
    if(X<=1 || N==1)
    {
        if(X<=Y)
        {
            v.resize(1);
            v[0].push_back(X);
        }
        return v;
    }
    for(int y=min(X, Y); y>=1; y--)
    {
        vector<vector<int> > w = partitions(X-y, N-1, y);
        for(int i=0; i<w.size(); i++)
        {
          w[i].push_back(y);
          v.push_back(w[i]);
        }
    }
    return v;


   }

int main()
{
    vector<vector<int> > v = partitions(5, 3, 5);
    int i;
    for(i=0; i<v.size(); i++)
    {
        int x;
        for(x=0; x<v[i].size(); x++)
            printf("%d ", v[i][x]);
        printf("\n");
    }
    return 0;
}

【讨论】:

  • 我确信这很棒,但我不知道它是用什么语言编写的,我无法理解这一切。 Vector 是一种数组吗? push_back 是做什么的?
  • 它是 C++ ...您希望用什么语言回答?
  • 它是 C++,vector 是动态数组的 STL 实现。
  • C# 如果可以的话,但我不知道这里发生了什么。
  • 我没有足够的 C# 知识。 Vector 只是一个动态数组,push_back 在数组末尾插入一个元素。函数 partitions(X, N, Y) 将 X 的可能分区列表返回到最多 N 个堆栈中,其中没有一个堆栈大于 Y。
【解决方案3】:

这是 user434507 在 C# 中的回答:

class Program
{
    static void Main(string[] args)
    {
        var v = Partitions(5, 3, 5);

        for (int i = 0; i < v.Count; i++)
        {
            for (int x = 0; x < v[i].Count; x++)
                Console.Write(v[i][x] + " "); 
            Console.WriteLine();
        }
    }

    static private List<List<int>> Partitions(int total, int stacks, int max)
    {
        List<List<int>> partitions = new List<List<int>>();

        if (total <= 1 || stacks == 1)
        {
            if (total <= max)
            {
                partitions.Add(new List<int>());
                partitions[0].Add(total);
            }

            return partitions;
        }
        for (int y = Math.Min(total, max); y >= 1; y--)
        {
            var w = Partitions(total - y, stacks - 1, y);
            for (int i = 0; i < w.Count; i++)
            {
                w[i].Add(y);
                partitions.Add(w[i]);
            }
        }

        return partitions;
    }
}

【讨论】:

  • 更新了有意义的变量名
猜你喜欢
  • 2023-01-25
  • 2020-09-21
  • 2020-10-25
  • 2017-03-30
  • 2012-01-26
  • 1970-01-01
  • 2015-08-22
  • 2013-08-23
  • 2013-05-09
相关资源
最近更新 更多