编辑:路径,而不是线路 - 它可以缠绕和东西。该路径连接相邻的正方形。你不能走对角线。
此外,我提出的解决方案是尝试将每个可能的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;
}
*/
}
答案 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
映射。此地图中的最高值将指示原始地图上平均包含较高编号邻居的区域。在这些点之间旅行将使您更有可能正确地猜测更高编号的位置。