Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/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
Java 子集和的动态规划方法_Java_Algorithm_Recursion_Dynamic Programming_Subset - Fatal编程技术网

Java 子集和的动态规划方法

Java 子集和的动态规划方法,java,algorithm,recursion,dynamic-programming,subset,Java,Algorithm,Recursion,Dynamic Programming,Subset,给定以下输入 10 4 3 5 5 7 在哪里 我要打印的球员谁的合并分数加上总,所以输出可以 14因为玩家1+4的分数=3+7->10或者输出可以是23,因为玩家2+3的分数=5+5->10 所以它非常类似于子集和问题。我对动态编程比较陌生,但在获得stackoverflow的帮助、在线阅读动态编程教程并在过去3天在线观看了一些视频之后。到目前为止,我已经提供了以下代码 class Test { public static void main (String[] args) thro

给定以下输入

10 4 3 5 5 7
在哪里

我要打印的球员谁的合并分数加上总,所以输出可以
14
因为玩家1+4的分数=
3+7
->10或者输出可以是23,因为玩家2+3的分数=5+5->10

所以它非常类似于子集和问题。我对动态编程比较陌生,但在获得stackoverflow的帮助、在线阅读动态编程教程并在过去3天在线观看了一些视频之后。到目前为止,我已经提供了以下代码

class Test
{
    public static void main (String[] args) throws java.lang.Exception
    {
        int[] test = {3,5,5,7};
        getSolution(test,4,10);
    }

    //pass total score, #of players (size) and the actual scores by each player(arr)
    public static int getSolution(int[] arr,int size, int total){


        int W = total;
        int n = size;
        int[][] myArray = new int[W+1][size+1];

        for(int i = 0; i<size+1; i++)
        {
            myArray[i][0] = 1;
        }
        for(int j =1; j<W+1; j++)
        {
            myArray[0][j] = 0;
        }

        for(int i =1; i<size+1; i++)
        {
            for(int x=1; x<W+1; x++)
            {
                if(arr[i] < x)
                {
                    myArray[i][x] = myArray[i-1][x];
                }
                else
                {
                    myArray[i][x] = myArray[i-1][x-arr[i]];
                }
            }
        }

        return myArray[n][W];
    }

}
类测试
{
公共静态void main(字符串[]args)引发java.lang.Exception
{
int[]测试={3,5,5,7};
getSolution(试验,4,10);
}
//通过总分、球员人数(人数)和每位球员的实际得分(arr)
公共静态int-getSolution(int[]arr,int-size,int-total){
int W=总数;
int n=大小;
int[][]myArray=newint[W+1][size+1];

对于(inti=0;i我可以尝试一些东西

首先,你传递了一个有4个值的数组,但后来你说只有3个玩家。我想这会给你带来一些困难

为了实现我能想到的最快的编程方式,我可以试试这个

public static void getSolution(int[] array, int desiredTotal) {
    for (int firstIndex = 0; firstIndex < array.size - 1; ++firstIndex) {
        getSolutionWith(array, desiredTotal, firstIndex);
    }
}

public static void getSolutionWith(int[] array, int desiredTotal, int firstIndex) {
    int lookFor = desiredTotal - array[firstIndex];
    for (int secondIndex = firstIndex + 1; secondIndex < array.size; ++secondIndex) {
        if (array[secondIndex] == lookFor) {
            System.out.printf("%d %d\n", firstIndex + 1, secondIndex + 1);
        }
    }
}
公共静态void getSolution(int[]数组,int desiredTotal){
for(int firstIndex=0;firstIndex

我还没有测试过这段代码,所以它可能并不完美。基本上你从0开始(第一个人),然后看看其他人,看看第一个人的值+第二个人的值是否等于你的总数。如果是这样,你就打印它们。

你的问题在这部分代码中

            if(arr[i] < x)
            {
                myArray[i][x] = myArray[i-1][x];
            }
            else
            {
                myArray[i][x] = myArray[i-1][x-arr[i]];
            }
你也有数组索引问题。你的<代码> i>代码>代码> x>代码>都从1开始,你永远不会考虑索引0,这实际上是你的第一个玩家。你需要使用<代码> ARR[I-1 ] /代码>值

因此,进一步的更新将如下所示

        myArray[i][x] = myArray[i-1][x];//carrying previous result
                if(x>=arr[i-1] )
                {
                    if (myArray[i][x]==1){
                        myArray[i][x]=1; 
                    }
                    else{
                        myArray[i][x] = myArray[i-1][x-arr[i-1]];
                    }
                }
所以最终的计划是这样的

    public boolean findSolution(int[] scores, int total) {
    int W = total;
    int players = scores.length;

    boolean[][] myArray = new boolean[players + 1][total + 1];

    for (int player = 0; player <= players; player++) {
        myArray[player][0] = true;
    }
    for (int score = 1; score < total; score++) {
        myArray[0][score] = false;
    }
    for (int player = 1; player <= players; player++) {
        for (int score = 1; score <= total; score++) {
            myArray[player][score] = myArray[player - 1][score];
            if (score >= scores[player - 1]) {
                myArray[player][score] = myArray[player - 1][score
                        - scores[player - 1]]
                        || myArray[player][score];
            }
        }
    }
    return myArray[players][W];

}
公共布尔查找解决方案(int[]分数,int总数){
int W=总数;
int players=scores.length;
布尔值[][]myArray=新布尔值[players+1][total+1];

对于(int player=0;player,这里有一个超级简单的解决方案,它只需在输入数组上生成一个幂集,然后对每个幂集进行迭代,查看其总和是否满足给定的总和。我将它与

O(2n)在时间和空间上。总量

您可以使用
集合的思想将所有索引存储到数组中,然后生成这些索引的所有排列,然后使用每组索引返回到数组中并获取值

输入
  • 目标:
    10
  • 值:
    [3,5,5,7]
代码:
import java.util.*;
导入java.lang.*;
导入java.io.*;
类子类
{
公用静态设置电源集(设置原始设置)
{
Set Set=新的HashSet();
if(originalSet.isEmpty())
{
add(newhashset());
返回集;
}
列表列表=新的ArrayList(originalSet);
T head=list.get(0);
Set rest=newhashset(list.subList(1,list.size());
用于(组:动力组(其余))
{
Set newSet=newhashset();
新闻集添加(标题);
newSet.addAll(集合);
添加(新闻集);
集合。添加(集合);
}       
返回集;
}
公共静态void main(字符串[]args)
{
Set mySet=newhashset();
int[]arr={3,5,5,7};
int目标=10;
int numVals=4;
对于(int i=0;i
public List findSubsetWithSum(int[]分数,int totalScore)
{
int players=score.length;
int[]cameFrom=newint[totalScore+1];
int[]pickedPlayer=新int[totalScore+1];
对于(int s=0;s 0&&cameFrom[s]>=0;s=cameFrom[s])
{
picked.add(pickedPlayer[s]);
}
回采;
}

main
呼叫的大小是3而不是4。这是有意的吗?第一:你的英语很棒!第二,我们的限制是只考虑学生的成对分数吗?也就是说,如果输入是
10 2 3 4 1 4
,我们可以组合
2 3 4 1
得到
10
(4名学生)错误@NathanTuggy oops刚刚意识到……我会马上解决的。@AndyG谢谢!是的,你可以根据需要合并任意多个玩家的分数,只要他们加在一起就可以了total@user2733436:恐怕您的问题是子集和。最坏情况下的精确算法仍然具有指数时间复杂性。也就是说,作为初学者,您最好尝试一下生成每一个可能的学生子集,然后计算该子集的和。这只有在可以使用大小为2的子集发现解决方案时才有效。根据OP的注释,任何大小的子集都是可能的。(因此,这是实际的子集和问题)我刚刚更新了我的问题,子集可以是任意大小的,而且我不需要打印所有可能等于分数的组合,我可以打印任何等于分数的组合。此外,最高总分可以是1000分。然后使较低的方法递归,传递到目前为止的总和。嗨,我只是尝试了你的解决方案,实际上它是这样的没有返回任何内容。我正在尝试在这里测试它…Geh。我在编辑时删除了一条重要的行;
的第一个单元格的初始化来自
。现在它已修复。感谢您提供的实时演示和解决方案,我将立即测试它。感谢muchi接受了您的回答。谢谢
        myArray[i][x] = myArray[i-1][x];//carrying previous result
                if(x>=arr[i-1] )
                {
                    if (myArray[i][x]==1){
                        myArray[i][x]=1; 
                    }
                    else{
                        myArray[i][x] = myArray[i-1][x-arr[i-1]];
                    }
                }
    public boolean findSolution(int[] scores, int total) {
    int W = total;
    int players = scores.length;

    boolean[][] myArray = new boolean[players + 1][total + 1];

    for (int player = 0; player <= players; player++) {
        myArray[player][0] = true;
    }
    for (int score = 1; score < total; score++) {
        myArray[0][score] = false;
    }
    for (int player = 1; player <= players; player++) {
        for (int score = 1; score <= total; score++) {
            myArray[player][score] = myArray[player - 1][score];
            if (score >= scores[player - 1]) {
                myArray[player][score] = myArray[player - 1][score
                        - scores[player - 1]]
                        || myArray[player][score];
            }
        }
    }
    return myArray[players][W];

}
import java.util.*;
import java.lang.*;
import java.io.*;

class SubsetSum
{
    public static <T> Set<Set<T>> powerSet(Set<T> originalSet)
    {
        Set<Set<T>> sets = new HashSet<Set<T>>();
        if (originalSet.isEmpty()) 
        {
            sets.add(new HashSet<T>());
            return sets;
        }
        List<T> list = new ArrayList<T>(originalSet);
        T head = list.get(0);
        Set<T> rest = new HashSet<T>(list.subList(1, list.size())); 
        for (Set<T> set : powerSet(rest))
        {
            Set<T> newSet = new HashSet<T>();
            newSet.add(head);
            newSet.addAll(set);
            sets.add(newSet);
            sets.add(set);
        }       
        return sets;
    }

    public static void main(String[] args)
    {
        Set<Integer> mySet = new HashSet<Integer>();
        int[] arr={3, 5, 5, 7};
        int target = 10;
        int numVals = 4;
        for(int i=0;i<numVals;++i)
        {
            mySet.add(i);
        }
        System.out.println("Solutions: ");
        for (Set<Integer> s : powerSet(mySet)) 
        {
            int sum = 0;
            for (Integer e : s)
            {
                sum += arr[e];
            }
            if (sum == target)
            {
                String soln = "[ ";
                for (Integer e : s)
                {
                    soln += arr[e];
                    soln += " ";
                }
                soln += "]";

                System.out.println(soln);
            }
        }
    }
}
public List<Integer> findSubsetWithSum(int[] score, int totalScore)
{
    int players = score.length;

    int[] cameFrom = new int[totalScore+1];
    int[] pickedPlayer = new int[totalScore+1];
    for (int s = 0; s <= totalScore; s++)
    {
        cameFrom[s] = -1;
        pickedPlayer[s] = -1;
    }
    cameFrom[0] = 0;
    for (int p = 0; p < players; p++)
    {
        for (int s = score[p]; s <= totalScore; s++)
        {
            if (cameFrom[s - score[p]] >= 0)
            {
                cameFrom[s] = s - score[p];
                pickedPlayer[s] = p + 1;
            }
        }
    }
    List<Integer> picked = new ArrayList<Integer>();
    for (int s = totalScore; s > 0 && cameFrom[s] >= 0; s = cameFrom[s])
    {
        picked.add(pickedPlayer[s]);
    }
    return picked;
}