我是Stack Overflow的新手,但我之前尝试过研究这个问题而且我已经提出了很多问题。我目前正在做家庭作业,我对如何使用教授给我的提示感到非常困惑。赋值的目的是找到从n位锁中的起始码到目标码的最短路径。这是一个例子
开始代码:5555
目标代码:7777
我们还有一些我们无法通过的禁用代码
例
禁止代码的数量= 4
6555
5655
5565
5556
根据这些信息,我们可以提出最短路径
D1 4555
U2 4655
U2 4755
U1 5755
U1 6755
U1 7755
U3 7765
U3 7775
U4 7776
U4 7777
总共10个动作。这也需要按字典顺序排列。意思是可以使多个10次移动到达这个目标代码但是我需要一个接近于形式的 D1 D2 ... DN U1 U2 ... UN
现在我已经为这个问题提出了许多解决方案。我的第一次尝试是通过n位代码并确定所有需要先减少的数字,然后我将每个数字从左到右依次设置。这会产生一些满足分配的答案,但是,它并没有解决在路径中间某处遇到禁止代码并且有一个特别长的绕行(基本上不是最短路径)的问题。
现在我不久前给出的提示是使用所有可能的一位数移动的队列,但我完全不知道如何从这个队列中获取最短路径。这是我到目前为止的代码
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
class Element
{
int index;
StringBuilder stringIndex;
boolean isForbid;
boolean visited;
boolean isTarget;
boolean pathForbid;
ArrayList<LinkedList<Integer>> paths;
Element()
{
index = 0;
isForbid = false;
visited = false;
isTarget = false;
pathForbid = false;
stringIndex = new StringBuilder();
paths = new ArrayList<LinkedList<Integer>>();
}
Element(int ind, boolean forb, boolean vis, boolean tar)
{
index = ind;
stringIndex = new StringBuilder();
stringIndex.append(ind);
isForbid = forb;
visited = vis;
isTarget = tar;
pathForbid = false;
paths = new ArrayList<LinkedList<Integer>>();
}
void setPath(int index, int n)
{
for(int i = 0; i < 2*n; i++)
{
LinkedList<Integer> newList = new LinkedList<Integer>();
newList.add(index);
paths.add(newList);
}
}
void setForbid(boolean forbid)
{
isForbid = forbid;
}
}
public class Solution
{
public Element moveOne(Element e, int index, int direction)
{
int num = Character.getNumericValue(e.stringIndex.charAt(index));
if(num == 0 && direction == 1)
num = 9;
else if(num == 9 && direction == 0)
num = 0;
else if(direction == 0)
num++;
else if(direction == 1)
num--;
String stringNum = Integer.toString(num);
e.stringIndex.replace(index, index+1, stringNum);
e.index = Integer.parseInt(e.stringIndex.toString());
return e;
}
public void printEl(Element e)
{
System.out.println(e.index);
System.out.println(e.stringIndex);
System.out.println(e.isForbid);
System.out.println(e.visited);
System.out.println(e.isTarget);
System.out.println(e.paths);
}
public void calcOneMoves(Element e, int n, Element[] all, int start)
{
int num = 0, index = start, newIndex = 0, w = 0;
String stringNum = "";
//current.append(start);
boolean forbidden = false;
ArrayList<LinkedList<Integer>> newPath = new ArrayList<LinkedList<Integer>>();
LinkedList<Integer> newList = new LinkedList<Integer>();
for(int j = 0; j < 2*n; j++)
{
StringBuilder current = new StringBuilder();
w = j;
newList = e.paths.get(j);
current.append(newList.getLast());
if(j >= n)
w = j - n;
if(j < (2*n)/2)
{
if(j % 2 == 0)
{
num = Character.getNumericValue(current.charAt(w));
num--;
stringNum = Integer.toString(num);
current.replace(w, w+1, stringNum);
newIndex = Integer.parseInt(current.toString());
newList.add(newIndex);
if(all[newIndex].isForbid)
newList.addFirst(-2);
else if(all[newIndex].isTarget)
newList.addFirst(-1);
else
all[newIndex].visited = true;
}
else if(j % 2 == 1)
{
num = Character.getNumericValue(current.charAt(w));
num--;
stringNum = Integer.toString(num);
current.replace(w, w+1, stringNum);
newIndex = Integer.parseInt(current.toString());
newList.add(newIndex);
if(all[newIndex].isForbid)
newList.addFirst(-2);
else if(all[newIndex].isTarget)
newList.addFirst(-1);
else
all[newIndex].visited = true;
}
}
else
{
if(j % 2 == 1)
{
num = Character.getNumericValue(current.charAt(w));
num++;
stringNum = Integer.toString(num);
current.replace(w, w+1, stringNum);
newIndex = Integer.parseInt(current.toString());
newList.add(newIndex);
if(all[newIndex].isForbid)
newList.addFirst(-2);
else if(all[newIndex].isTarget)
newList.addFirst(-1);
}
else if(j % 2 == 0)
{
num = Character.getNumericValue(current.charAt(w));
num++;
stringNum = Integer.toString(num);
current.replace(w, w+1, stringNum);
newIndex = Integer.parseInt(current.toString());
newList.add(newIndex);
if(all[newIndex].isForbid)
newList.addFirst(-2);
else if(all[newIndex].isTarget)
newList.addFirst(-1);
else
all[newIndex].visited = true;
}
}
e.stringIndex.replace(0, n, Integer.toString(start));
//e.paths.add(newList);
current = e.stringIndex;
}
}
public int findDiff(Element temp, Element target, int index)
{
int num1 = Character.getNumericValue(temp.stringIndex.charAt(index));
int num2 = Character.getNumericValue(target.stringIndex.charAt(index));
return num1 - num2;
}
public static void main(String[] args) throws Exception
{
System.setIn(new FileInputStream(new File("Input.txt")));
String[] upDown = {"U", "D"};
Scanner scanner = new Scanner(System.in);
Solution s = new Solution();
int i, f, n, size = 1, pow, count = 0, difference = 0, direction = 0, tempNum = 0;
boolean goAhead = true, failed = false, done = false, stillDecreasing = true;
Element startCode;
Element targetCode;
Element tempCode = new Element();
StringBuilder output = new StringBuilder();
n = scanner.nextInt();
for(i = 0; i < n; i++)
size = size*10;
Element arr[] = new Element[size];
for(i = 0; i < size; i++)
{
Element e = new Element(i, false, false, false);
e.setPath(i, n);
arr[i] = e;
}
boolean decreaseFirst[] = new boolean[n];
tempNum = scanner.nextInt();
startCode = new Element(tempNum, false, true, false);
startCode.setPath(tempNum, n);
tempNum = scanner.nextInt();
targetCode = new Element(tempNum, false, true, true);
targetCode.setPath(tempNum, n);
arr[startCode.index] = startCode;
arr[targetCode.index] = targetCode;
if(scanner.hasNext())
{
f = scanner.nextInt();
for(i = 0; i < f; i++)
{
tempNum = scanner.nextInt();
Element newElement = new Element(tempNum, true, true, false);
newElement.setPath(tempNum, n);
arr[newElement.index] = newElement;
}
}
tempCode = startCode;
int tempIndex = startCode.index;
s.calcOneMoves(tempCode, n, arr, tempCode.index);
s.calcOneMoves(tempCode, n, arr, tempCode.index);
s.printEl(tempCode);
if(arr[startCode.index].isForbid || arr[targetCode.index].isForbid)
{
goAhead = false;
failed = true;
}
/*if(n == 1 && goAhead)
{
difference = s.findDiff(tempCode, targetCode, 0);
while(tempCode.stringIndex.charAt(0) != targetCode.stringIndex.charAt(0))
{
if(difference > 5 || (difference > -5 && difference < 0))
{
tempCode = s.moveOne(tempCode, 0, 0);
count++;
direction = 0;
if(arr[tempCode.index] == null)
arr[tempCode.index] = tempCode;
else if(arr[tempCode.index].isForbid)
{
for(int w = 0; w < count; w++)
tempCode = s.moveOne(tempCode, 0, 1);
count = 0;
difference = 5;
output = new StringBuilder();
if(done)
{
tempCode = targetCode;
failed = true;
}
else
done = true;
}
}
else if(difference <= 5 || (difference <= -5 && difference < 0))
{
tempCode = s.moveOne(tempCode, 0, 1);
count++;
direction = 1;
if(arr[tempCode.index] == null)
arr[tempCode.index] = tempCode;
else if(arr[tempCode.index].isForbid)
{
for(int w = 0; w < count; w++)
tempCode = s.moveOne(tempCode, 0, 0);
count = 0;
difference = 6;
output = new StringBuilder();
if(done)
{
tempCode = targetCode;
failed = true;
}
else
done = true;
}
}
output.append("\n" + upDown[direction]+ "" + (i+1) + " " + tempCode.index);
}
}
if(goAhead)
{
for(i = 0; i < n; i++)
{
while(tempCode.stringIndex.charAt(i) != targetCode.stringIndex.charAt(i) && stillDecreasing)
{
difference = s.findDiff(tempCode, targetCode, i);
if((difference <= 5 && difference > 0)|| (difference <= -5 && difference < 0))
{
tempCode.isForbid = false;
tempCode = s.moveOne(tempCode, i, 1);
count++;
direction = 1;
if(arr[tempCode.index] == null)
arr[tempCode.index] = tempCode;
else if(arr[tempCode.index].isForbid)
{
tempCode = s.moveOne(tempCode, i, 0);
count--;
stillDecreasing = false;
}
if(tempCode.stringIndex.charAt(0) == '0')
output.append("\n" + upDown[direction] + "" + (i+1) + " " + "0" + tempCode.index);
else
output.append("\n" + upDown[direction] + "" + (i+1) + " " + tempCode.index);
}
else
stillDecreasing = false;
}
stillDecreasing = true;
}
}
if(goAhead)
{
for(i = 0; i < n; i++)
{
while(tempCode.stringIndex.charAt(i) != targetCode.stringIndex.charAt(i))
{
difference = s.findDiff(tempCode, targetCode, i);
if(difference > 5 || (difference > -5 && difference < 0))
{
tempCode.isForbid = false;
tempCode = s.moveOne(tempCode, i, 0);
count++;
direction = 0;
if(arr[tempCode.index] == null)
arr[tempCode.index] = tempCode;
else if (arr[tempCode.index].isForbid)
{
tempCode = s.moveOne(tempCode, i, 1);
tempCode = s.moveOne(tempCode, i, 1);
direction = 1;
if(arr[tempCode.index] == null)
arr[tempCode.index] = tempCode;
else if(arr[tempCode.index].isForbid)
{
tempCode = s.moveOne(tempCode, i, 0);
count--;
}
tempCode.isForbid = true;
}
if(tempCode.stringIndex.charAt(0) == '0')
output.append("\n" + upDown[direction] + "" + (i+1) + " " + "0" + tempCode.index);
else
output.append("\n" + upDown[direction] + "" + (i+1) + " " + tempCode.index);
if(tempCode.isForbid)
break;
}
else if(difference <= 5 || (difference <= -5 && difference < 0))
{
tempCode.isForbid = false;
tempCode = s.moveOne(tempCode, i, 1);
count++;
direction = 1;
if(arr[tempCode.index] == null)
arr[tempCode.index] = tempCode;
else if (arr[tempCode.index].isForbid)
{
direction = 0;
tempCode = s.moveOne(tempCode, i, 0);
tempCode = s.moveOne(tempCode, i, 0);
if(arr[tempCode.index] == null)
arr[tempCode.index] = tempCode;
else if(arr[tempCode.index].isForbid)
{
tempCode = s.moveOne(tempCode, i, 1);
count--;
}
tempCode.isForbid = true;
}
if(tempCode.stringIndex.charAt(0) == '0')
output.append("\n" + upDown[direction] + "" + (i+1) + " " + "0" + tempCode.index);
else
output.append("\n" + upDown[direction] + "" + (i+1) + " " + tempCode.index);
if(tempCode.isForbid)
break;
}
}
if(tempCode.stringIndex.charAt(0) != targetCode.stringIndex.charAt(0) && tempCode.stringIndex.charAt((1)) == targetCode.stringIndex.charAt((1)) && n != 1)
i = -1;
else if(tempCode.stringIndex.charAt(i) != targetCode.stringIndex.charAt(i) && tempCode.stringIndex.charAt((i)) == targetCode.stringIndex.charAt((i)) && n != 1)
i = -1;
else if(i == (n - 1) && tempCode.index != targetCode.index)
failed = true;
}
}
/*if(failed)
System.out.println(-1);
else
System.out.println(count + "" + output);*/
}
}
截至目前,这段代码有点凌乱,因为我已经实现了一堆不同的想法。一旦找到有效的解决方案,我会清理它。底部注释掉的代码是我如何实现我的一条路径,先从减少开始,然后从左到右依次设置每个数字。
如果您现在运行此代码,输入格式为
4 //锁定中的位数在0 <0的范围内。 n <= 7
5555 //开始代码
7777 //目标代码
4 //禁止代码的数量
6555
5655
5565
5556
它实际输出的是链接列表的arraylist,每个链接列表包含一位数的移动,但是你注意到它不是一个数字移动。此外,您在我的列表中看到的任何负数都是我的数字编码方式,用于解释我是否在我的路径中遇到了禁止的号码,或者我是否击中了我的目标
非常感谢任何帮助/建议
答案 0 :(得分:0)
使用图搜索算法,例如Dijkstra算法。看看那个和其他图表搜索。我不太了解你的实施情况,但这是一个很好的起点。