有趣的16x16网格总和

时间:2016-10-13 18:04:17

标签: java algorithm sum

编辑:路径,而不是线路 - 它可以缠绕和东西。该路径连接相邻的正方形。你不能走对角线。

此外,我提出的解决方案是尝试将每个可能的50位数字串4 - 这样,从每个方块开始,然后向左,向右,向上或向下移动---在每种可能的组合中4 ^ 50

此问题要求您在此16x16网格中找到可以通过路径连接的50个数字的最大总和,而不是对角线:

                         {{50,54,46,55,45,56,44,53,47,59,41,60,40,59,41,59},
                          {47,57,46,49,52,46,53,47,53,41,59,40,60,41,59,41},
                          {56,42,54,51,48,54,47,53,53,57,48,54,49,57,46,59},
                          {48,50,52,54,56,58,57,47,48,49,48,47,46,53,52,51},
                          {50,56,50,48,49,50,51,59,42,60,39,62,38,63,38,50},
                          {60,40,50,50,50,50,60,40,55,45,55,45,56,44,56,44},
                          {60,45,46,37,56,50,43,39,50,53,56,39,50,58,39,49},
                          {26,56,54,38,48,50,67,64,32,54,50,49,48,47,46,45},
                          {28,45,35,57,54,34,34,32,64,57,58,74,24,64,34,50},
                          {40,50,60,54,45,56,46,47,35,36,39,27,38,50,51,52},
                          {29,38,47,58,48,37,50,58,37,46,50,50,50,50,50,50},
                          {47,48,49,50,52,65,64,52,49,47,43,47,58,46,30,32},
                          {59,47,47,56,65,34,45,56,75,24,35,45,56,65,50,54},
                          {53,46,35,45,29,46,46,50,23,32,40,46,64,64,64,20},
                          {53,54,56,58,60,43,43,34,34,35,64,30,50,40,49,59},

此算法尝试随机路径,并在50个步骤(向上,向右,向下,向左)中的每个步骤之后转弯,而不会越过自身。它让我大约2750,但我需要至少2800来完成任务。 //洛尔

import java.util.ArrayList;

public class lol
{
private int[][] square = {{50,54,46,55,45,56,44,53,47,59,41,60,40,59,41,59},
                          {47,57,46,49,52,46,53,47,53,41,59,40,60,41,59,41},
                          {56,42,54,51,48,54,47,53,53,57,48,54,49,57,46,59},
                          {48,50,52,54,56,58,57,47,48,49,48,47,46,53,52,51},
                          {50,56,50,48,49,50,51,59,42,60,39,62,38,63,38,50},
                          {60,40,50,50,50,50,60,40,55,45,55,45,56,44,56,44},
                          {60,45,46,37,56,50,43,39,50,53,56,39,50,58,39,49},
                          {26,56,54,38,48,50,67,64,32,54,50,49,48,47,46,45},
                          {28,45,35,57,54,34,34,32,64,57,58,74,24,64,34,50},
                          {40,50,60,54,45,56,46,47,35,36,39,27,38,50,51,52},
                          {29,38,47,58,48,37,50,58,37,46,50,50,50,50,50,50},
                          {47,48,49,50,52,65,64,52,49,47,43,47,58,46,30,32},
                          {59,47,47,56,65,34,45,56,75,24,35,45,56,65,50,54},
                          {53,46,35,45,29,46,46,50,23,32,40,46,64,64,64,20},
                          {53,54,56,58,60,43,43,34,34,35,64,30,50,40,49,59},
                          {52,12,17,50,63,62,62,64,50,51,52,57,43,44,42,69}};                         ;

    public static void main(String [] args)
{
    lol lol1 = new lol();
}
public lol()
{
    ArrayList<Integer> record = new ArrayList<Integer>();
    int max =0;
    for(int count = 0; count<10000; count++)
    {
        for(int startx=0; startx<16; startx++)
        {
            for(int starty =0; starty<16; starty++)
            {
                int[] pos = new int[2];
                pos[0] = starty;
                pos[1] = startx;
                ArrayList<Integer> past = new ArrayList<Integer>();
                int total = 0;

                for(int i=0; i<50; i++)
                {
                    int random = (int)(Math.random()*4);
                    int switchcount = 0;
                    past.add(100*pos[0] + pos[1]);
                    total+= square[pos[0]][pos[1]];

                    if(random == 0)
                    {
                        if(pos[0] == 0 || checkexists((pos[0]-1)*100+pos[1],past))
                        {
                            random++;
                            switchcount++;
                        }
                        else
                        {
                            pos[0]--;

                        }
                    }
                    if(random == 1)
                    {
                        if(pos[0] == 15 || checkexists((pos[0]+1)*100+pos[1],past))
                        {
                            random++;
                            switchcount++;
                        }
                        else
                        {
                            pos[0]++;

                        }
                    }
                    if(random == 2)
                    {
                        if(pos[1] == 0 || checkexists((pos[0])*100+pos[1]-1,past))
                        {
                            random++;
                            switchcount++;
                        }
                        else
                        {
                            pos[1]--;

                        }
                    }
                    if(random == 3)
                    {
                        if(pos[1] == 15 || checkexists((pos[0])*100+pos[1]+1,past))
                        {
                            if(switchcount >= 3)
                            {
                                break;
                            }
                            else
                            {
                                random = 0;
                                if(pos[0] == 0 || checkexists((pos[0]-1)*100+pos[1],past))
                                {
                                    random++;
                                    switchcount++;
                                }
                                else
                                {
                                    pos[0]--;

                                }
                                if(random == 1)
                                {
                                    if(pos[0] == 15 || checkexists((pos[0]+1)*100+pos[1],past))
                                    {
                                        random++;
                                        switchcount++;
                                    }
                                    else
                                    {
                                        pos[0]++;

                                    }
                                }

                                if(random == 2)
                                {
                                    if(pos[1] == 0 || checkexists((pos[0])*100+pos[1]-1,past))
                                    {
                                        break;
                                    }
                                    else
                                    {
                                        pos[1]--;

                                    }
                                }
                            }
                        }
                        else
                        {
                            pos[1]++;
                        }
                    }
                }
                if (total>max)
                {
                    max = total;
                    record = past;
                }







            }
        }
    }
    for(int p = 0; p<record.size(); p++)
    {
        System.out.println(record.get(p));
    }
    System.out.println("\n\n" + max);

}
public boolean checkexists(int pos, ArrayList<Integer> past)
{
    for(int i=0; i<past.size(); i++)
    {
        if(past.get(i) == pos)
        {
            //System.out.println("TRUE");
            return true;
        }
    }
    return false;
}
}

这是我尝试一个完整的解决方案 - 它试图取出每个可能的50位数字串4 - 这样,你从每个方块开始,向左,向右,向上或向下移动---每一个可能的组合4 ^ 50

import java.util.ArrayList;

    public class lol2
     {
     private int[][] square =      {{50,54,46,55,45,56,44,53,47,59,41,60,40,59,41,59},
                              {47,57,46,49,52,46,53,47,53,41,59,40,60,41,59,41},
                          {56,42,54,51,48,54,47,53,53,57,48,54,49,57,46,59},
                          {48,50,52,54,56,58,57,47,48,49,48,47,46,53,52,51},
                          {50,56,50,48,49,50,51,59,42,60,39,62,38,63,38,50},
                          {60,40,50,50,50,50,60,40,55,45,55,45,56,44,56,44},
                          {60,45,46,37,56,50,43,39,50,53,56,39,50,58,39,49},
                          {26,56,54,38,48,50,67,64,32,54,50,49,48,47,46,45},
                          {28,45,35,57,54,34,34,32,64,57,58,74,24,64,34,50},
                          {40,50,60,54,45,56,46,47,35,36,39,27,38,50,51,52},
                          {29,38,47,58,48,37,50,58,37,46,50,50,50,50,50,50},
                          {47,48,49,50,52,65,64,52,49,47,43,47,58,46,30,32},
                          {59,47,47,56,65,34,45,56,75,24,35,45,56,65,50,54},
                          {53,46,35,45,29,46,46,50,23,32,40,46,64,64,64,20},
                          {53,54,56,58,60,43,43,34,34,35,64,30,50,40,49,59},
                               {52,12,17,50,63,62,62,64,50,51,52,57,43,44,42,69}};

public static void main(String [] args)
{
    lol2 lol1 = new lol2();
}
public lol2()
{
    ArrayList<Integer> record = new ArrayList<Integer>();
    int max =0;
    for(int count = 0; count<10000; count++)
    {
        for(int startx=0; startx<16; startx++)
        {
            for(int starty =0; starty<16; starty++)
            {
                for(int a1 = 0; a1 <4; a1++) {
                    for(int a2 = 0; a2 <4; a2++) {
                        for(int a3 = 0; a3 <4; a3++) {
                            for(int a4 = 0; a4 <4; a4++) {
                                for(int a5 = 0; a5 <4; a5++) {
                                    for(int a6 = 0; a6 <4; a6++) {
                                        for(int a7 = 0; a7 <4; a7++) {
                                            for(int a8 = 0; a8 <4; a8++) {
                                                for(int a9 = 0; a9 <4; a9++) {
                                                    for(int a10 = 0; a10 <4; a10++) {
                                                        for(int a11 = 0; a11 <4; a11++) {
                                                            for(int a12 = 0; a12 <4; a12++) {
                                                                for(int a13 = 0; a13 <4; a13++) {
                                                                    for(int a14 = 0; a14 <4; a14++) {
                                                                        for(int a15 = 0; a15 <4; a15++) {
                                                                            for(int a16 = 0; a16 <4; a16++) {
                                                                                for(int a17 = 0; a17 <4; a17++) {
                                                                                    for(int a18 = 0; a18 <4; a18++) {
                                                                                        for(int a19 = 0; a19 <4; a19++) {
                                                                                            for(int a20 = 0; a20 <4; a20++) {
                                                                                                for(int a21 = 0; a21 <4; a21++) {
                                                                                                    for(int a22 = 0; a22 <4; a22++) {
                                                                                                        for(int a23 = 0; a23 <4; a23++) {
                                                                                                            for(int a24 = 0; a24 <4; a24++) {
                                                                                                                for(int a25 = 0; a25 <4; a25++) {
                                                                                                                    for(int a26 = 0; a26 <4; a26++) {
                                                                                                                        for(int a27 = 0; a27 <4; a27++) {
                                                                                                                            for(int a28 = 0; a28 <4; a28++) {
                                                                                                                                for(int a29 = 0; a29 <4; a29++) {
                                                                                                                                    for(int a30 = 0; a30 <4; a30++) {
                                                                                                                                        for(int a31 = 0; a31 <4; a31++) {
                                                                                                                                            for(int a32 = 0; a32 <4; a32++) {
                                                                                                                                                for(int a33 = 0; a33 <4; a33++) {
                                                                                                                                                    for(int a34 = 0; a34 <4; a34++) {
                                                                                                                                                        for(int a35 = 0; a35 <4; a35++) {
                                                                                                                                                            for(int a36 = 0; a36 <4; a36++) {
                                                                                                                                                                for(int a37 = 0; a37 <4; a37++) {
                                                                                                                                                                    for(int a38 = 0; a38 <4; a38++) {
                                                                                                                                                                        for(int a39 = 0; a39 <4; a39++) {
                                                                                                                                                                            System.out.println("SPAM");
                                                                                                                                                                            for(int a40 = 0; a40 <4; a40++) {
                                                                                                                                                                                for(int a41 = 0; a41 <4; a41++) {
                                                                                                                                                                                    for(int a42 = 0; a42 < 4; a42++){
                                                                                                                                                                                        for(int a43=0; a43<4; a43++){
                                                                                                                                                                                            for(int a44 =0; a44<4; a44++){
                                                                                                                                                                                                for(int a45=0; a45<4; a45++){
                                                                                                                                                                                                    for(int a46=0; a46<4; a46++){
                                                                                                                                                                                                        for(int a47=0; a47<4; a47++){
                                                                                                                                                                                                            for(int a48=0; a48<4; a48++){
                                                                                                                                                                                                                for(int a49=0; a49<4; a49++){
                                                                                                                                                                                                                    for(int a50=0; a50<4; a50++){
                                                                                                                                                                                                                        int[] pos = new int[2];
                                                                                                                                                                                                                        pos[0] = starty;
                                                                                                                                                                                                                        pos[1] = startx;
                                                                                                                                                                                                                        ArrayList<Integer> past = new ArrayList<Integer>();
                                                                                                                                                                                                                        int total = 0;
                                                                                                                                                                                                                        String path = "" + a1 + a2+a3+a4+a5+a6+a7+a8+a9+a10+a11+a12+a13+a14+a15+a16+a17+a18+a19+a20+a21+a22+a23+a24+a25+a26+a27+a28+a29+a30+a31+a32+a33+a34+a35+a36+a37+a38+a39+a40+a41+a42+a43+a44+a45+a46+a47+a48+a49+a50;
                                                                                                                                                                                                                        for(int i =0; i<50; i++)
                                                                                                                                                                                                                                {

                                                                                                                                                                                                                                    int random = Integer.parseInt(path.substring(i,i+1));
                                                                                                                                                                                                                                    int switchcount = 0;

                                                                                                                                                                                                                                    past.add(100*pos[0] + pos[1]);
                                                                                                                                                                                                                                                        total+= square[pos[0]][pos[1]];

                                                                                                                                                                                                                                                        if(random == 0)
                                                                                                                                                                                                                                                        {
                                                                                                                                                                                                                                                            if(pos[0] == 0 || checkexists((pos[0]-1)*100+pos[1],past))
                                                                                                                                                                                                                                                            {
                                                                                                                                                                                                                                                                random++;
                                                                                                                                                                                                                                                                switchcount++;
                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                            else
                                                                                                                                                                                                                                                            {
                                                                                                                                                                                                                                                                pos[0]--;

                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                        }
                                                                                                                                                                                                                                                        if(random == 1)
                                                                                                                                                                                                                                                        {
                                                                                                                                                                                                                                                            if(pos[0] == 15 || checkexists((pos[0]+1)*100+pos[1],past))
                                                                                                                                                                                                                                                            {
                                                                                                                                                                                                                                                                random++;
                                                                                                                                                                                                                                                                switchcount++;
                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                            else
                                                                                                                                                                                                                                                            {
                                                                                                                                                                                                                                                                pos[0]++;

                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                        }
                                                                                                                                                                                                                                                        if(random == 2)
                                                                                                                                                                                                                                                        {
                                                                                                                                                                                                                                                            if(pos[1] == 0 || checkexists((pos[0])*100+pos[1]-1,past))
                                                                                                                                                                                                                                                            {
                                                                                                                                                                                                                                                                random++;
                                                                                                                                                                                                                                                                switchcount++;
                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                            else
                                                                                                                                                                                                                                                            {
                                                                                                                                                                                                                                                                pos[1]--;

                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                        }
                                                                                                                                                                                                                                                        if(random == 3)
                                                                                                                                                                                                                                                        {
                                                                                                                                                                                                                                                            if(pos[1] == 15 || checkexists((pos[0])*100+pos[1]+1,past))
                                                                                                                                                                                                                                                            {
                                                                                                                                                                                                                                                                if(switchcount >= 3)
                                                                                                                                                                                                                                                                {
                                                                                                                                                                                                                                                                    break;
                                                                                                                                                                                                                                                                }
                                                                                                                                                                                                                                                                else
                                                                                                                                                                                                                                                                {
                                                                                                                                                                                                                                                                    random = 0;
                                                                                                                                                                                                                                                                    if(pos[0] == 0 || checkexists((pos[0]-1)*100+pos[1],past))
                                                                                                                                                                                                                                                                    {
                                                                                                                                                                                                                                                                        random++;
                                                                                                                                                                                                                                                                        switchcount++;
                                                                                                                                                                                                                                                                    }
                                                                                                                                                                                                                                                                    else
                                                                                                                                                                                                                                                                    {
                                                                                                                                                                                                                                                                        pos[0]--;

                                                                                                                                                                                                                                                                    }
                                                                                                                                                                                                                                                                    if(random == 1)
                                                                                                                                                                                                                                                                    {
                                                                                                                                                                                                                                                                        if(pos[0] == 15 || checkexists((pos[0]+1)*100+pos[1],past))
                                                                                                                                                                                                                                                                        {
                                                                                                                                                                                                                                                                            random++;
                                                                                                                                                                                                                                                                            switchcount++;
                                                                                                                                                                                                                                                                        }
                                                                                                                                                                                                                                                                        else
                                                                                                                                                                                                                                                                        {
                                                                                                                                                                                                                                                                            pos[0]++;

                                                                                                                                                                                                                                                                        }
                                                                                                                                                                                                                                                                    }

                                                                                                                                                                                                                                                                    if(random == 2)
                                                                                                                                                                                                                                                                    {
                                                                                                                                                                                                                                                                        if(pos[1] == 0 || checkexists((pos[0])*100+pos[1]-1,past))
                                                                                                                                                                                                                                                                        {
                                                                                                                                                                                                                                                                            break;
                                                                                                                                                                                                                                                                        }
                                                                                                                                                                                                                                                                        else
                                                                                                                                                                                                                                                                        {
                                                                                                                                                                                                                                                                            pos[1]--;

                                                                                                                                                                                                                                                                        }
                                                                                                                                                                                                                                                                    }
                                                                                                                                                                                                                                                                }
                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                            else
                                                                                                                                                                                                                                                            {
                                                                                                                                                                                                                                                                pos[1]++;
                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                        }
                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                        if (total>max) max = total;f
                                                                                                                                                                                                                    }
                                                                                                                                                                                                                }
                                                                                                                                                                                                            }
                                                                                                                                                                                                        }
                                                                                                                                                                                                    }
                                                                                                                                                                                                }
                                                                                                                                                                                            }
                                                                                                                                                                                        }
                                                                                                                                                                                    }
                                                                                                                                                                                }
                                                                                                                                                                            }
                                                                                                                                                                        }

                                                                                                                                                                    }
                                                                                                                                                                }
                                                                                                                                                            }
                                                                                                                                                        }
                                                                                                                                                    }
                                                                                                                                                }
                                                                                                                                            }
                                                                                                                                        }
                                                                                                                                    }
                                                                                                                                }
                                                                                                                            }
                                                                                                                        }
                                                                                                                    }
                                                                                                                }
                                                                                                            }
                                                                                                        }
                                                                                                    }
                                                                                                }
                                                                                            }
                                                                                        }
                                                                                    }
                                                                                }
                                                                            }
                                                                        }
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    for(int p = 0; p<record.size(); p++)
    {
        System.out.println(record.get(p));
    }
    System.out.println("\n\n" + max);

}
public boolean checkexists(int pos, ArrayList<Integer> past)
{
    for(int i=0; i<past.size(); i++)
    {
        if(past.get(i) == pos)
        {
            //System.out.println("TRUE");
            return true;
        }
    }
    return false;
}
/*public ArrayList<String> setint()
{
    ArrayList<String> bob = new ArrayList<String>();
    for(BigInteger i =1267650600228229401496703205376; ; i<2535301200456458802993406410752; i++)
    {
        String number = i + "";
        bob.add(BigInteger.toString(BigInteger.parseInt(number, 10), 4));
    }
    return bob;
}
*/

}

3 个答案:

答案 0 :(得分:3)

编辑:这是一些示例代码,展示了我概述的一些技术。它很好地解决了这个问题。在进行实验时,我确实发现了一些不在下面的代码中的改进。提高该计划的速度/效率是100%可能的,但留作任何未来读者的练习

import java.util.*;
public class SquareSolver {
/**
 * The LRU_Cache data structure is useful in a LOT of optimization problems, where storing all the problems you've solved so far
 * is infeasible, but there's significant time savings to be had if your program can
 * realize "Wait, I've solved this sub-problem already", and just re-use earlier answers.
 * It stores things, until it gets above LRUCacheSize, then it automatically ejects the least recently used entry.
 * This is strictly an optimization, because things get ejected from the cache automatically, you should not rely on
 * presence (or not) of an element for correctness.
 */
private HashMap<Integer, LRUCache> leastRecentlyUsedCache;
private Map<Integer, Integer> bestShortPathScores;
private Map<Integer, Integer> depthEarlyCutoffsMap;
private Map<Integer, Integer> depthCacheHitsMap;
private int squareSize, targetLength;
private Map<Coords, Integer> coordScores;
private Set<Coords> neighborOffsets;
private Path bestPath;
private boolean isLongPath;
private long startTime;
private long timeout;
private class LRUCache extends LinkedHashMap<Path, Integer>{
    private int LRUCacheSize;
    LRUCache(int LRUCacheSize){
        super(LRUCacheSize * 4 / 3, 0.75f, true);
       this.LRUCacheSize = LRUCacheSize;
    }
    @Override
    protected boolean removeEldestEntry(Map.Entry eldest) {
        return size() > LRUCacheSize;
    }
}
public SquareSolver(int LRUCacheSize, int squareSize, int targetLength) {
    neighborOffsets = new HashSet<>(Arrays.asList(new Coords[]{new Coords(-1, 0), new Coords(1, 0), new Coords(0, -1), new Coords(0, 1)}));
    this.targetLength = targetLength;
    this.squareSize = squareSize;
    leastRecentlyUsedCache = new HashMap<>();
    for(int i = 0; i <= targetLength; i++) {
        leastRecentlyUsedCache.put(i, new LRUCache(LRUCacheSize / targetLength));
    }
    coordScores = new HashMap<>();
}

public static void main(String[] args) {
    int[][] testSquare = new int[][]{
            {50, 54, 46, 55, 45, 56, 44, 53, 47, 59, 41, 60, 40, 59, 41, 59},
            {47, 57, 46, 49, 52, 46, 53, 47, 53, 41, 59, 40, 60, 41, 59, 41},
            {56, 42, 54, 51, 48, 54, 47, 53, 53, 57, 48, 54, 49, 57, 46, 59},
            {48, 50, 52, 54, 56, 58, 57, 47, 48, 49, 48, 47, 46, 53, 52, 51},
            {50, 56, 50, 48, 49, 50, 51, 59, 42, 60, 39, 62, 38, 63, 38, 50},
            {60, 40, 50, 50, 50, 50, 60, 40, 55, 45, 55, 45, 56, 44, 56, 44},
            {60, 45, 46, 37, 56, 50, 43, 39, 50, 53, 56, 39, 50, 58, 39, 49},
            {26, 56, 54, 38, 48, 50, 67, 64, 32, 54, 50, 49, 48, 47, 46, 45},
            {28, 45, 35, 57, 54, 34, 34, 32, 64, 57, 58, 74, 24, 64, 34, 50},
            {40, 50, 60, 54, 45, 56, 46, 47, 35, 36, 39, 27, 38, 50, 51, 52},
            {29, 38, 47, 58, 48, 37, 50, 58, 37, 46, 50, 50, 50, 50, 50, 50},
            {47, 48, 49, 50, 52, 65, 64, 52, 49, 47, 43, 47, 58, 46, 30, 32},
            {59, 47, 47, 56, 65, 34, 45, 56, 75, 24, 35, 45, 56, 65, 50, 54},
            {53, 46, 35, 45, 29, 46, 46, 50, 23, 32, 40, 46, 64, 64, 64, 20},
            {53, 54, 56, 58, 60, 43, 43, 34, 34, 35, 64, 30, 50, 40, 49, 59},
            {52, 12, 17, 50, 63, 62, 62, 64, 50, 51, 52, 57, 43, 44, 42, 69}};
    SquareSolver testSolver = new SquareSolver(500 * 1000, 16, 50);
    Path bestPath = testSolver.solveSquare(testSquare, 30 * 1000);
    System.out.println("Best Score:\t" + bestPath.getScore());
    System.out.println("Best Path:\t" + bestPath.toString());
}

private boolean inSquare(Coords coords) {
    int x = coords.getX();
    int y = coords.getY();
    return x >= 0 && y >= 0 && x < squareSize && y < squareSize;
}

public void solveSquareHelper(Path currentPath) {
    // Base Case
    if (currentPath.size() == targetLength) {
        synchronized (bestPath) {
            if (currentPath.getScore() > bestPath.getScore()) {
                System.out.print(".");
                bestPath = currentPath;
            }
        }
        return;
    }

    // Don't run forever.
    if (System.currentTimeMillis() > startTime + timeout){
        return;
    }

    // Least Recently Used Cache can save us a lot of work
    if (lru_hit(currentPath)) {
        return;
    }

    // Early Cutoff can save us a lot of work too
    if (can_early_cutoff(currentPath)) {
        return;
    }

    // Recursive Case
    expandLegalNeighbors(currentPath);
}

private void expandLegalNeighbors(Path currentPath) {
    Coords currentCoords = currentPath.getCurrentCoords();
    neighborOffsets.stream()
            .map(currentCoords::add)                    // Get all neighbors of current coords
            .filter(this::inSquare)                     // Filter out coords outside the square
            .filter(currentPath::doesNotContain)        // Filter out coords already in currentPath
            .sorted(Comparator.comparing(Coords::getProximityToOrigin)) // This order maximizes the usefulness of LRUCache
            .forEachOrdered(neighbor ->
                    solveSquareHelper(new Path(currentPath, neighbor)));
}

private boolean can_early_cutoff(Path currentPath) {
    int futurePathLength = targetLength - currentPath.size();
    int upperBoundFutureScore = bestShortPathScores.get(futurePathLength);
    if (currentPath.getScore() + upperBoundFutureScore <= bestPath.getScore()) {
        depthEarlyCutoffsMap.put(currentPath.size(), depthEarlyCutoffsMap.get(currentPath.size()) + 1);
        return true;
    } else {
        return false;
    }
}

private boolean lru_hit(Path currentPath) {
    LRUCache currentDepthCache = leastRecentlyUsedCache.get(currentPath.size());
    if (currentDepthCache.containsKey(currentPath)) {
        depthCacheHitsMap.put(currentPath.size(), depthCacheHitsMap.get(currentPath.size()) + 1);
        currentDepthCache.put(currentPath, currentDepthCache.get(currentPath) + 1);
        return true;
    } else {
        currentDepthCache.put(currentPath, 0);
    }
    return false;
}
public Path solveSquare(int[][] square, long timeout){
    Map<Integer, Integer> smallPathScores = new HashMap<>();
    smallPathScores.put(1, -10);
    for(int i =0; i < squareSize; i++){
        for(int j = 0; j < squareSize; j++){
            if(square[i][j] > smallPathScores.get(1)){
                smallPathScores.put(1, square[i][j]);
            }
        }
    }
    Coords fakeCoords = new Coords(-10, -10);
    coordScores.put(fakeCoords, -10);
    Path bestSmallPath = new Path(fakeCoords);
    for(int i = 2; i < targetLength; i++){
        SquareSolver smallSolver = new SquareSolver(500 * 1000, squareSize, i);
        bestSmallPath = smallSolver.solveSquare(square, timeout * i, smallPathScores, bestSmallPath);
        smallPathScores.put(i, bestSmallPath.getScore());
        System.gc();
    }
    return solveSquare(square, timeout * targetLength, smallPathScores, bestSmallPath);
}
public Path solveSquare(int[][] square, long timeout, Map<Integer, Integer> shortPathScores, Path initialBestPath) {
    bestPath = initialBestPath;
    bestShortPathScores = shortPathScores;
    System.out.println("=============================Target Length:\t" + targetLength + "(Timeout:\t" + timeout/60000.0 + " minutes)===========================");
    System.out.println("Best Short Path Scores (for early cutoff):\t" + bestShortPathScores);
    startTime = System.currentTimeMillis();
    this.timeout = timeout;
    depthCacheHitsMap = new HashMap<>();
    depthEarlyCutoffsMap = new HashMap<>();
    for (int i = 1; i < targetLength; i++) {
        depthCacheHitsMap.put(i, 0);
        depthEarlyCutoffsMap.put(i, 0);
    }
    for (int i = 0; i < squareSize; i++) {
        for (int j = 0; j < squareSize; j++) {
            coordScores.put(new Coords(i, j), square[i][j]);
        }
    }
    System.out.print("Expanding from best shorter node");
    expandLegalNeighbors(initialBestPath);
    System.out.println("Starting from every spot");
    coordScores.keySet()
            .stream()
            .sorted(Comparator.comparing(Coords::getProximityToOrigin))
            .forEachOrdered(startingCoords -> solveSquareHelper(new Path(startingCoords)));
    System.out.println();
    System.out.println("Best Path:\t" + bestPath);
    System.out.println("Best Score:\t" + bestPath.getScore());
    System.out.println("LRU Cache stats:\t" + depthCacheHitsMap);
    System.out.println("Early Cutoff stats:\t" + depthEarlyCutoffsMap);
    return bestPath;
}

private class Coords implements Comparable<Coords> {
    private int x, y;
    private double proximityToOrigin;

    Coords(int x, int y) {
        this.x = x;
        this.y = y;
        this.proximityToOrigin = Math.sqrt((x - squareSize/2) * (x - squareSize/2) + (y - squareSize/2) * (y - squareSize/2));
    }

    int getX() {
        return this.x;
    }

    int getY() {
        return this.y;
    }

    double getProximityToOrigin() {
        return proximityToOrigin;
    }

    Coords add(Coords other) {
        return new Coords(this.x + other.x, this.y + other.y);
    }

    @Override
    public int compareTo(Coords o) {
        int xdiff = this.x - o.x;
        if (xdiff == 0) return this.y - o.y;
        else return xdiff;

    }

    @Override
    public boolean equals(Object other) {
        if (other instanceof Coords) {
            Coords o = (Coords) other;
            return this.x == o.x && this.y == o.y;
        } else {
            return false;
        }
    }

    @Override
    public int hashCode() {
        return this.x * squareSize + this.y;
    }

    @Override
    public String toString() {
        return "(" + this.x + ", " + this.y + ")";
    }
}

private class Path {
    private TreeSet<Coords> usedCoords;
    private Coords currentCoords;
    private int score;

    Path(Coords newCoords) {
        this.usedCoords = new TreeSet<>();
        usedCoords.add(newCoords);
        currentCoords = newCoords;
        this.score = coordScores.get(newCoords);
    }

    Path(Path previousPath, Coords newCoords) {
        this(newCoords);
        this.usedCoords.addAll(previousPath.usedCoords);
        this.score += previousPath.score;
    }

    Coords getCurrentCoords() {
        return this.currentCoords;
    }

    int size() {
        return usedCoords.size();
    }

    int getScore() {
        return this.score;
    }

    boolean doesNotContain(Coords coords) {
        return !usedCoords.contains(coords);
    }

    @Override
    public String toString() {
        return this.usedCoords.toString();
    }

    @Override
    public int hashCode() {
        return this.usedCoords.hashCode();
    }

    @Override
    public boolean equals(Object other) {
        if (other instanceof Path) {
            Path o = (Path) other;
            return this.usedCoords.equals(o.usedCoords) && this.currentCoords.equals(o.currentCoords);
        } else {
            return false;
        }
    }
}
}

一些关键见解让我们能够比蛮力做更有效的事情:

洞察具有相同当前节点和相同使用节点集的两个子路径具有相同的最高分。

我们如何使用使用LRU_Cache来识别使用相同节点并具有相同当前节点的路径。这导致许多早期截止,深度早到4.根节点相对于主树的深度为4的子树各包含3 ^ 46个路径。将相当一部分修剪掉是很大的。

洞察力长度为k的子路径只能获得子路径的最高分数.score + best_length_n-k_path.score

我们如何使用首先解决长度为2的最佳路径,然后使用它来查找长度为3的最佳路径。使用它们来查找长度为4的最佳路径,等等你可以随时提前切断长度为k的当前路径,即使添加了你之前的最佳nk长度路径,也不能超过最大分数。解决n = 2,3,4,5 ... 50似乎比直接解决n = 50更多的工作,但对于这个问题,结果证明早期修剪的节省更多。

答案 1 :(得分:2)

如果线条不能是对角线,这是一种方法 它(试图)检查每种可能性:

Test.java

import java.util.ArrayList;

public class Test {
    private int[][] square =    
       {{50,54,46,55,45,56,44,53,47,59,41,60,40,59,41,59},
        {47,57,46,49,52,46,53,47,53,41,59,40,60,41,59,41},
        {56,42,54,51,48,54,47,53,53,57,48,54,49,57,46,59},
        {48,50,52,54,56,58,57,47,48,49,48,47,46,53,52,51},
        {50,56,50,48,49,50,51,59,42,60,39,62,38,63,38,50},
        {60,40,50,50,50,50,60,40,55,45,55,45,56,44,56,44},
        {60,45,46,37,56,50,43,39,50,53,56,39,50,58,39,49},
        {26,56,54,38,48,50,67,64,32,54,50,49,48,47,46,45},
        {28,45,35,57,54,34,34,32,64,57,58,74,24,64,34,50},
        {40,50,60,54,45,56,46,47,35,36,39,27,38,50,51,52},
        {29,38,47,58,48,37,50,58,37,46,50,50,50,50,50,50},
        {47,48,49,50,52,65,64,52,49,47,43,47,58,46,30,32},
        {59,47,47,56,65,34,45,56,75,24,35,45,56,65,50,54},
        {53,46,35,45,29,46,46,50,23,32,40,46,64,64,64,20},
        {53,54,56,58,60,43,43,34,34,35,64,30,50,40,49,59},
        {52,12,17,50,63,62,62,64,50,51,52,57,43,44,42,69}};

    int result = 0;

    Test()
    {
        for (int i = 0; i < 15; i++)
            for (int j = 0; j < 15; j++)
                search(new Position(i,j), new ArrayList<Position>(), 0); //Starts at every position
        System.out.println(result);
    }

    public void search(Position actual, ArrayList<Position> checked, int sum){
    checked.add(actual); //Add the actual position to avoid going through it multiple times
    sum += square[actual.row][actual.column];

    if (checked.size() != 50)
        for (int i = 0; i < 2; i++)
            for (int j = -1; j < 2; j += 2){ //Checks every direction
                boolean checkable = true;
                Position newpos;

                if (i != 0)
                    newpos = new Position(actual.row, actual.column + j);
                else
                    newpos = new Position(actual.row + j, actual.column);

                if (newpos.row >= 0 && newpos.column >= 0 && newpos.row <= 15 && newpos.column <= 15){
                    for (Position pos : checked)
                        if(pos.equals(newpos)) //If the new position has already been calculated
                            checkable = false;

                    if(checkable)
                        search(newpos, new ArrayList<Position>(checked), sum); //If the position haven't been checked, starts a new search
                }
            }

    if (sum > result){
        result = sum;
        System.out.println(sum);
    }
}

}

Position.java

public class Position{
    public int row, column;

    Position(int x, int y){
        row = x;
        column = y;
    }

    public boolean equals(Position pos) {
        return pos.row == this.row && pos.column == this.column;
    }
}

Main.java

public class Main {
    public static void main(String [] args){
        new Test();
    }
}

当前输出:2578
评论我是否忘记了/有任何建议/问题
执行时间非常低

编辑:当我使用以下方式打印选中列表的大小时:

    if (sum > result){
        result = sum;
        System.out.println(checked.size());
    }

它超过了50 ......尽管它不应该。有什么想法?
在这里,count + checked.size()应始终等于50

编辑2: 发现它!
我只需为每次搜索创建一个新数组:

if(checkable)
    search(newpos, count, new ArrayList<Position>(checked), sum);

只是意识到要检查16 * 16 * 3 ^ 50个案例......嗯,值得一试

答案 2 :(得分:1)

我觉得一个好的起点就是找到最强烈的区域。

策略可以将每个位置排列为其邻居的总和乘以以每个位置为中心的Gaussian distribution

rank(a, b) = 0
for j in -16 to 16:
    for k in -16 to 16:
        rank(a, b) += value(a+j, b+k)*exp(-((a)^2+(b)^2)/constant)

value(x, y)是原始地图中的值,而constant是衰减因子。超出原始范围的值被视为零。

对每个像素执行此操作后,将形成一个新的rank映射。此地图中的最高值将指示原始地图上平均包含较高编号邻居的区域。在这些点之间旅行将使您更有可能正确地猜测更高编号的位置。

相关问题