Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.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#_Sql Server_Algorithm_Combinations - Fatal编程技术网

C# 组合、电源甚至不知道从哪里开始

C# 组合、电源甚至不知道从哪里开始,c#,sql-server,algorithm,combinations,C#,Sql Server,Algorithm,Combinations,我有这个问题,我希望人们能给我指出正确的方向,因为我甚至不知道从哪里开始 这是设置,我在SQL Server中有两个表,表A是一个汇总表,表B是一个详细信息表,如下所示: Table A ParentID Total Amount 1 100 2 587 Table B ParentID ChildID Amount 1 1 8 1

我有这个问题,我希望人们能给我指出正确的方向,因为我甚至不知道从哪里开始

这是设置,我在SQL Server中有两个表,表A是一个汇总表,表B是一个详细信息表,如下所示:

Table A
ParentID        Total Amount
1               100
2               587


Table B
ParentID        ChildID         Amount
1               1               8
1               2               7
1               3               18
1               4               93
2               5               500
2               6               82
2               7               5
2               8               10
因此,对于每个ParentID,我需要计算出其数量总和等于父项总数的子项的组合

所以对于parentID1(100),它将是childID2和4(7+93),我将忽略childID1和3

对于ParentID 2,它将是孩子5、6、7,而我将忽略8

子组合没有固定的大小,可以组合为与父组合相等

所以做一些研究,我需要得到每个父母所有孩子的幂集。然后从那里我可以总结他们的总金额,看看他们是否等于父母。但是,如果我错了,请纠正我,但是如果集合中有N个项目,那么幂集合将由2^N个组合组成

其中一些父母有超过750个孩子,2^750是一个非常大的数字。我基本上是一个.NET/SQL Server的家伙,但我愿意尝试任何人们认为适合这份工作的技术

所以有几个问题

1) 我应该继续努力找出每一位家长的电源设置,还是我用它找错了方向?
2) 这是一个已经解决的问题,而我只是在谷歌上找不到它?
3) 假设可以做到这一点,那么解决这个问题的正确方法是什么?

一项研究告诉我,你可以在N*2^p中解决这个问题,其中N是子项的数量,p是存储最大数字所需的位数。看,说,这里:

=============================================

只要每个父级的子级数很小,那么计算功率集就可以了,但是请注意,N个子级的功率集是2^N,增长非常快。2^750大得令人绝望,大约10^225

有很多函数用于查找powerset,我主要使用Java,我知道Guava中有一个,我认为Apache Commoms Math中也有一个。构造一个powerset并不困难,直觉上你可以认为它是一个深度为N的二叉树,其中每个级别都是“我是否包含此元素是/否”

我不是用c语言写的,而是用伪代码写的

Set<Set<Object>> Powerset(Set<Set<Object>> powerset, Object newItem){
    Set<Set<Object>> newSet = powerset.clone();
    for (Set<Object> set : newSet){
        set.add(newItem)
    }
    return newSet.addAll(powerset)
}
Set Powerset(Set Powerset,Object newItem){
Set newSet=powerset.clone();
用于(设置:新闻集){
set.add(newItem)
}
return newSet.addAll(powerset)
}
因此,这将获取N个元素的幂集,并返回N+1个元素的幂集。因此,您可以重复调用它来构建从空集开始的powerset

对于较大数量的子级,请使用相同的函数,而不是构建功率集,但删除总和超过目标的任何集。(很明显,它是单调递增的,因此一旦超过目标,就不能继续。例如,假设Object.hasValue()返回一个数字,然后执行以下操作:

Set<Set<Object>> Powerset(Set<Set<Object>> powerset, Object newItem, int target){
    Set<Set<Object>> newSet = powerset.clone();
    for (Set<Object> set : newSet){
        set.add(newItem)
    }


    Set<Set<Object>> result = new Set<Set<Object>>();
    for(Set<Object> set : newSet){
        int sum = 0;
        for(Object o : set){
            sum += o.hasvalue();
        }
        if(sum <= target){
            result.add(set)
        }
    }
    return result.addAll(powerset);
}
Set Powerset(Set Powerset,Object newItem,int target){
Set newSet=powerset.clone();
用于(设置:新闻集){
set.add(newItem)
}
集合结果=新集合();
用于(设置:新闻集){
整数和=0;
用于(对象o:集){
sum+=o.hasvalue();
}

如果(sum如果一些父母有750个孩子,你的时间就快用完了。如果你想在太阳熄灭之前得到答案,你应该研究某种并行云计算解决方案

2^750 = 5922386521
        532855740161817506647119
        732883018558947359509044
        845726112560091729648156
        474603305162988578607512
        400425457279991804428268
        870599332596921062626576
        000993556884845161077691
        136496092218188572933193
        945756793025561702170624
现在,让我们假设我们真的很幸运,就像中了彩票一样幸运,并且很早就找到了正确的组合

现在,让我们假设我们有一台速度很快的计算机,它可以每秒计算十亿个和

这将需要像这样的时间

6.332987 * 10^135 years
找到答案。现在这仍然是一段难以想象的长时间。你可以把它想象为

4.52356 * 10^125 ages of the universe.
或者更具体地说,宇宙的年龄乘以宇宙中原子的数量的时间更长。这是一个很长的时间

这是一些猜测,但我怀疑宇宙中没有足够的物质来制造足够的计算机来并行计算,以在太阳耗尽燃料之前完成计算。(这是现有技术的界限。)


我建议应该放弃蛮力幂集方法。计算机很快,但没有那么快。

这个问题可以归结为子集问题,而子集问题可以归结为简单的背包问题。 该问题有一个动态规划解决方案:-

W = knapsack capacity = Total Amount of parent.

item weight = item cost = child amount.

maximize profit and if W = profit then there exists a subset else not.
使用kanpsack的DP解决方案来解决这个问题,并通过回溯得到结果

下面是一个JAVA解决方案,您可以将其转换为C#:-

公共类子类{
静态int[][]成本;
公共静态void计算集(int目标,int[]arr){
成本=新整数[arr.length][target+1];

对于(int j=0;j实际上,您的情况并不像2^750分析所显示的那样糟糕。放弃幂集解决方案,转而使用动态规划。一个选项可能如下所示:

public static IEnumerable<int> FindSet(IEnumerable<int> amounts, int target)
{
    var results = new Dictionary<int, List<int>>();
    results[0] = new List<int>();
    foreach(var amount in amounts)
    {
        for(int i = 0; i <= target; i++)
        {
            if(!results.ContainsKey(i) || results[i].Contains(amount))
                continue;
            var combination = new List<int>(results[i]);
            combination.Add(amount);
            if (i + amount == target)
                return combination;
            results[i + amount] = combination;
        }
    }
    return null;
}

那么你就不必一直复制列表了

是的,不幸的是,表A的每一行似乎都会给你一个子集和问题,这个问题是NP完全问题。如果实际的总数本身不是太大,是整数,你仍然可以用伪多项式时间算法有效地解决它——这应该足以让谷歌满意另一件需要注意的事情是,如果不明显:表a中的每一行可以有多个解决方案。例如,想象一下,如果总数为50,有100个子行,每个子行的值为1:那么(100选择50)子行的任何组合都有效。
public static IEnumerable<int> FindSet(IEnumerable<int> amounts, int target)
{
    var results = new Dictionary<int, List<int>>();
    results[0] = new List<int>();
    foreach(var amount in amounts)
    {
        for(int i = 0; i <= target; i++)
        {
            if(!results.ContainsKey(i) || results[i].Contains(amount))
                continue;
            var combination = new List<int>(results[i]);
            combination.Add(amount);
            if (i + amount == target)
                return combination;
            results[i + amount] = combination;
        }
    }
    return null;
}
public class Node
{
    public int Value;
    public Node Parent;

    public List<int> ToList()
    {
        if(Parent == null)
        {
            return new List<int> { Value };
        }
        var result = Parent.ToList();
        result.Add(Value);
        return result;
    }
}