Java 求最大值的优化算法

Java 求最大值的优化算法,java,arrays,algorithm,dynamic-programming,Java,Arrays,Algorithm,Dynamic Programming,我需要设计一个算法,以找到在预定义的(步长)下沿int[]步进得到的最大值 输入是我们可以“使用”每个步长的次数;由n2、n5和n10给出。n2表示在阵列中移动2个点,n5表示5个点,n10表示10个点。我们只能前进(从左到右) int[]包含值1..5,数组大小为(n2*2+n5*5+n10*10)。起点是int[0] 示例:我们从int[0]开始。从这里我们可以移动到int[0+2]==3,int[0+5]==4或int[0+10]==1。让我们转到int[5],因为它的值最高。从int[5

我需要设计一个算法,以找到在预定义的(步长)下沿int[]步进得到的最大值

输入是我们可以“使用”每个步长的次数;由n2、n5和n10给出。n2表示在阵列中移动2个点,n5表示5个点,n10表示10个点。我们只能前进(从左到右)

int[]包含值1..5,数组大小为(n2*2+n5*5+n10*10)。起点是int[0]

示例:我们从int[0]开始。从这里我们可以移动到int[0+2]==3,int[0+5]==4或int[0+10]==1。让我们转到int[5],因为它的值最高。从int[5]我们可以移动到int[5+2],int[5+5]或int[5+10]等等

我们应该以2、5或10的步长沿着阵列移动(并且我们只能使用每个步长n2、n5和n10次),这样我们就可以在阵列中步进以收集尽可能高的总和

public class Main {

private static int n2 = 5;
private static int n5 = 3;
private static int n10 = 2;
private static final int[] pokestops = new int[n2 * 2 + n5 * 5 + n10 * 10];

public static void main(String[] args) {

    Random rand = new Random();
    for (int i = 0; i < pokestops.length; i++) {
        pokestops[i] = Math.abs(rand.nextInt() % 5) + 1;
    }
    System.out.println(Arrays.toString(pokestops));
    //TODO: return the maximum value possible
}
}
输出是可能的最大值

public class Main {

private static int n2 = 5;
private static int n5 = 3;
private static int n10 = 2;
private static final int[] pokestops = new int[n2 * 2 + n5 * 5 + n10 * 10];

public static void main(String[] args) {

    Random rand = new Random();
    for (int i = 0; i < pokestops.length; i++) {
        pokestops[i] = Math.abs(rand.nextInt() % 5) + 1;
    }
    System.out.println(Arrays.toString(pokestops));
    //TODO: return the maximum value possible
}
}
公共类主{
私有静态int n2=5;
专用静态int n5=3;
专用静态int n10=2;
私有静态最终整数[]pokestops=新整数[n2*2+n5*5+n10*10];
公共静态void main(字符串[]args){
Random rand=新的Random();
for(int i=0;i
这是一个伪代码的答案(我没有运行它,但它应该可以工作)

用-1填充dp。
dp(整数id、整数2步计数、整数5步计数、整数10步计数){
如果(id>array_length-1)返回0;
如果(dp[id][2stepcount][5stepcount][10stepcount]!=-1)返回dp[id][2stepcount][5stepcount][10stepcount];
else dp[id][2步数][5步数][10步数]=0;
int 2step=2stepcount
打电话给dp(0,0,0,0),答案是dp[0][0][0]

如果你想倒退,那么你可以这样做:

fill dp with -1.

dp(int id, int 2stepcount, int 5stepcount, int 10stepcount) {
  if(id > array_length - 1 || id < 0) return 0;

  if(dp[id][2stepcount][5stepcount][10stepcount] != -1) return dp[id][2stepcount][5stepcount][10stepcount];
  else dp[id][2stepcount][5stepcount][10stepcount] = 0;

  int 2stepForward = 2stepcount < max2stepcount? dp(id + 2, 2stepcount + 1, 5stepcount, 10stepcount) : 0;
  int 5stepForward = 5stepcount < max5stepcount? dp(id + 5, 2stepcount, 5stepcount + 1, 10stepcount) : 0;
  int 10stepForward = 10stepcount < max10stepcount? dp(id + 10, 2stepcount, 5stepcount, 10stepcount + 1) : 0;

  int 2stepBackward = 2stepcount < max2stepcount? dp(id - 2, 2stepcount + 1, 5stepcount, 10stepcount) : 0;
  int 5stepBackward = 5stepcount < max5stepcount? dp(id - 5, 2stepcount, 5stepcount + 1, 10stepcount) : 0;
  int 10stepBackward = 10stepcount < max10stepcount? dp(id - 10, 2stepcount, 5stepcount, 10stepcount + 1) : 0;

  dp[id][2stepcount][5stepcount][10stepcount] += array[id] + max(2stepForward, 5stepForward, 10stepForward, 2stepBackward, 5backForward, 10backForward);
  return dp[id][2stepcount][5stepcount][10stepcount];
}
用-1填充dp。
dp(整数id、整数2步计数、整数5步计数、整数10步计数){
如果(id>array|u length-1 | id<0)返回0;
如果(dp[id][2stepcount][5stepcount][10stepcount]!=-1)返回dp[id][2stepcount][5stepcount][10stepcount];
else dp[id][2步数][5步数][10步数]=0;
int 2STEPTFORWARD=2STEPCUNT

但是您的路径没有得到充分的探索,因为如果索引为负数或大于数组大小-1,我们将停止,我想您可以添加环绕功能。

您需要计算以下动态编程dp[c2][c5][c10][id]-其中c2是您已步进2的次数,c5-乘以5,c10-乘10和id-您当前的位置在哪里。我将只为c2和c5编写示例,它可以很容易地扩展

int[][][][] dp = new int[n2 + 1][n5 + 1][pokestops.length + 1];
for (int[][][] dp2 : dp) for (int[][] dp3 : dp2) Arrays.fill(dp3, Integer.MAX_VALUE);
dp[0][0][0] = pokestops[0];
for (int c2 = 0; c2 <= n2; c2++) {
  for (int c5 = 0; c5 <= n5; c5++) {
    for (int i = 0; i < pokestops.length; i++) {
      if (c2 < n2 && dp[c2 + 1][c5][i + 2] < dp[c2][c5][i] + pokestops[i + 2]) {
        dp[c2 + 1][c5][i + 2] = dp[c2][c5][i] + pokestops[i + 2];
      }  
      if (c5 < n5 && dp[c2][c5 + 1][i + 5] < dp[c2][c5][i] + pokestops[i + 5]) {
        dp[c2][c5 + 1][i + 5] = dp[c2][c5][i] + pokestops[i + 5];
      }  
    }   
  }
}
int[]dp=newint[n2+1][n5+1][pokestops.length+1];
for(int[][]dp2:dp)for(int[]dp3:dp2)数组。fill(dp3,Integer.MAX_值);
dp[0][0][0]=pokestops[0];

对于(int c2=0;c2这是一个解决方案,但我不确定它有多最优

我对它做了一些优化,但我认为可以做得更多

我把它和有问题的例子一起贴了出来

import java.util.Arrays;
import java.util.Random;

public class FindMax {


private static int n2 = 5;
private static int n5 = 3;
private static int n10 = 2;
private static final int[] pokestops = new int[n2 * 2 + n5 * 5 + n10 * 10];


public static int findMaxValue(int n2, int n5, int n10, int pos, int[] pokestops) {
    System.out.print("|");
    if (n2 <= 0 || n5 <= 0 || n10 <= 0) {
        return 0;
    }
    int first;
    int second;
    int third;
    if (pokestops[pos] == 5 || ((first = findMaxValue(n2 - 1, n5, n10, pos + 2, pokestops)) == 5) || ((second = findMaxValue(n2, n5 - 1, n10, pos + 5, pokestops)) == 5) || ((third = findMaxValue(n2, n5, n10 - 1, pos + 10, pokestops)) == 5)) {
        return 5;
    }
    return Math.max(Math.max(Math.max(first, second), third), pokestops[pos]);
}

public static void main(String[] args) {

    Random rand = new Random();
    for (int i = 0; i < pokestops.length; i++) {
        pokestops[i] = Math.abs(rand.nextInt() % 5) + 1;
    }
    System.out.println(Arrays.toString(pokestops));
    //TODO: return the maximum value possible
    int max = findMaxValue(n2, n5, n10, 0, pokestops);
    System.out.println("");
    System.out.println("Max is :" + max);
}
导入java.util.array;
导入java.util.Random;
公共类FindMax{
私有静态int n2=5;
专用静态int n5=3;
专用静态int n10=2;
私有静态最终整数[]pokestops=新整数[n2*2+n5*5+n10*10];
公共静态int findMaxValue(int n2、int n5、int n10、int pos、int[]pokestops){
系统输出打印(“|”);

如果(n2我知道目标语言是java,但我喜欢pyhton,转换不会很复杂。 您可以定义一个四维数组dp,其中dp[i][a][b][c]是您可以定义的最大值 当你已经有了a长度2b长度5c长度 10。我通常会得到更干净的代码

import random

values = []
memo = {}

def dp(pos, n2, n5, n10):
    state = (pos, n2, n5, n10)
    if state in memo:
        return memo[state]
    res = values[pos]
    if pos + 2 < len(values) and n2 > 0:
        res = max(res, values[pos] + dp(pos + 2, n2 - 1, n5, n10))
    if pos + 5 < len(values) and n5 > 0:
        res = max(res, values[pos] + dp(pos + 5, n2, n5 - 1, n10))
    if pos + 10 < len(values) and n10 > 0:
        res = max(res, values[pos] + dp(pos + 10, n2, n5, n10 - 1))
    memo[state] = res
    return res

n2, n5, n10 = 5, 3, 2

values = [random.randint(1, 5) for _ in range(n2*2 + n5*5 + n10*10)]

print dp(0, n2, n5, n10)
随机导入
值=[]
备忘录={}
def dp(位置、n2、n5、n10):
状态=(位置,n2,n5,n10)
如果在备忘录中注明:
返回备忘录[状态]
res=值[pos]
如果pos+20:
res=最大值(res,数值[pos]+dp(pos+2,n2-1,n5,n10))
如果位置+50:
res=最大值(res,数值[pos]+dp(pos+5,n2,n5-1,n10))
如果位置+100:
res=最大值(res,数值[pos]+dp(pos+10,n2,n5,n10-1))
备忘录[状态]=res
返回res
n2,n5,n10=5,3,2
值=[范围内(n2*2+n5*5+n10*10)的随机.randint(1,5)]
打印dp(0、n2、n5、n10)

疑似家庭作业。未测试:

import java.util.Arrays;
import java.util.Random;

public class Main {

    private static Step[] steps = new Step[]{
            new Step(2, 5),
            new Step(5, 3),
            new Step(10, 2)
    };

    private static final int[] pokestops = new int[calcLength(steps)];

    private static int calcLength(Step[] steps) {
        int total = 0;
        for (Step step : steps) {
            total += step.maxCount * step.size;
        }
        return total;
    }

    public static void main(String[] args) {

        Random rand = new Random();
        for (int i = 0; i < pokestops.length; i++) {
            pokestops[i] = Math.abs(rand.nextInt() % 5) + 1;
        }
        System.out.println(Arrays.toString(pokestops));

        int[] initialCounts = new int[steps.length];
        for (int i = 0; i < steps.length; i++) {
            initialCounts[i] = steps[i].maxCount;
        }

        Counts counts = new Counts(initialCounts);
        Tree base = new Tree(0, null, counts);
        System.out.println(Tree.max.currentTotal);

    }


    static class Tree {
        final int pos;
        final Tree parent;
        private final int currentTotal;

        static Tree max = null;

        Tree[] children = new Tree[steps.length*2];
        public Tree(int pos, Tree parent, Counts counts) {
            this.pos = pos;
            this.parent = parent;
            if (pos < 0 || pos >= pokestops.length || counts.exceeded()) {
                currentTotal = -1;
            } else {
                int tmp = parent == null ? 0 : parent.currentTotal;
                this.currentTotal = tmp + pokestops[pos];
                if (max == null || max.currentTotal < currentTotal) max = this;
                for (int i = 0; i < steps.length; i++) {
                    children[i] = new Tree(pos + steps[i].size, this, counts.decrement(i));
                    // uncomment to allow forward-back traversal:
                    //children[2*i] = new Tree(pos - steps[i].size, this, counts.decrement(i));
                }
            }
        }
    }

    static class Counts {
        int[] counts;

        public Counts(int[] counts) {
            int[] tmp = new int[counts.length];
            System.arraycopy(counts, 0, tmp, 0, counts.length);
            this.counts = tmp;
        }

        public Counts decrement(int i) {
            int[] tmp = new int[counts.length];
            System.arraycopy(counts, 0, tmp, 0, counts.length);
            tmp[i] -= 1;
            return new Counts(tmp);
        }

        public boolean exceeded() {
            for (int count : counts) {
                if (count < 0) return true;
            }
            return false;
        }
    }

    static class Step {
        int size;
        int maxCount;

        public Step(int size, int maxCount) {
            this.size = size;
            this.maxCount = maxCount;
        }
    }
}
导入java.util.array;
进口