Java 到达终点位置的所有可能方法
对于那些不想点击它的人,它基本上说有一块垫脚石,“-”和士兵“#”,士兵只能向右移动。如果士兵在另一名士兵后面,他必须等待士兵先移动。结束条件是所有士兵到达终点 2名士兵可以跨越5块踏脚石的方式Java 到达终点位置的所有可能方法,java,algorithm,path,catalan,Java,Algorithm,Path,Catalan,对于那些不想点击它的人,它基本上说有一块垫脚石,“-”和士兵“#”,士兵只能向右移动。如果士兵在另一名士兵后面,他必须等待士兵先移动。结束条件是所有士兵到达终点 2名士兵可以跨越5块踏脚石的方式 1) ##--- #-#-- -##-- -#-#- --##- --#-# ---## 2) ##--- #-#-- -##-- -#-#- -#--# --#-# ---## 3) ##--- #-#-- #--#- -#-#- --##- --#-# ---##
1) ##--- #-#-- -##-- -#-#- --##- --#-# ---##
2) ##--- #-#-- -##-- -#-#- -#--# --#-# ---##
3) ##--- #-#-- #--#- -#-#- --##- --#-# ---##
4) ##--- #-#-- #--#- -#-#- -#--# --#-# ---##
5) ##--- #-#-- #--#- #---# -#--# --#-# ---##
我使用的是广度优先搜索,有5块石头,它在几秒钟内运行,但有10块石头,它需要几个小时,时间随着深度呈指数增长。我该怎么处理
我的代码:
States.java
import java.util.ArrayList;
public class State {
public int stones;
public Soldiers[] soldiers;
public String currentState ="";
public boolean visited = false;
public State(int stones,int Numsoldiers){
System.out.println(Numsoldiers);
this.stones = stones;
soldiers = new Soldiers[Numsoldiers];
System.out.println("length" + soldiers.length);
initState();
}
public State(int stones,Soldiers[] soldiers){
this.stones = stones;
this.soldiers = soldiers;
paintState();
}
public void initState(){
for(int i=0;i<soldiers.length;i++)
{
soldiers[i] = new Soldiers();
soldiers[i].position =i;
currentState+="#";
}
for(int j=soldiers.length;j<stones;j++)
{
currentState+="-";
}
}
private void paintState(){
for(int j=0;j<stones;j++)
{
currentState+="-";
}
char[] stateChar = currentState.toCharArray();
currentState = "";
for(int i=0;i<soldiers.length;i++){
stateChar[soldiers[i].position] = '#';
}
for(int k=0; k<stateChar.length;k++){
currentState += stateChar[k];
}
}
public void printState(){
System.out.println(currentState);
}
public ArrayList<State> getNextStates(){
ArrayList<State> States = new ArrayList<State>();
for(int i=0;i<soldiers.length;i++){
Soldiers[] newSoldiers = new Soldiers[soldiers.length];
for(int j=0;j<soldiers.length;j++){
newSoldiers[j] = new Soldiers(soldiers[j].position);
}
if(!((newSoldiers[i].position+1)==stones))
{
if((currentState.charAt((newSoldiers[i].position+1))=='-'))
{
newSoldiers[i].move();
States.add(new State(stones,newSoldiers));
}
}
}
if(States.size()==0)
{
TestSoldiers.count++;
}
return States;
}
}
test.java
public class Soldiers {
int position = 0;
public Soldiers(){
position =0;
}
public Soldiers(int pos){
position = pos;
}
public void move(){
position ++;
}
}
import java.util.LinkedList;
import java.util.Queue;
public class TestSoldiers {
public static int count=0;
public static void main(String[] args){
TestSoldiers t = new TestSoldiers();
}
public TestSoldiers()
{
State s = new State(10,3);
breadthFirstTraversal(s);
System.out.println(count);
}
public void breadthFirstTraversal(State rootNode){
Queue<State> q = new LinkedList<State>();
q.add(rootNode);
while(!q.isEmpty()){
State n = (State)q.poll();
n.printState();
for(State adj : n.getNextStates()){
q.add(adj);
}
}
}
}
import java.util.LinkedList;
导入java.util.Queue;
公营士兵{
公共静态整数计数=0;
公共静态void main(字符串[]args){
测试士兵t=新测试士兵();
}
公共测试士兵()
{
状态s=新状态(10,3);
横向第一次穿越;
系统输出打印项次(计数);
}
公共无效宽度第一次遍历(状态根节点){
队列q=新的LinkedList();
q、 添加(rootNode);
而(!q.isEmpty()){
State n=(State)q.poll();
n、 printState();
for(State adj:n.getNextStates()){
q、 添加(adj);
}
}
}
}
我如何才能使我只考虑每一个状态,同时保持结束的总数的完整性(TestPrave.java中的计数)? 对于那些想要修改参数的人来说,这是一个新的状态(n,k),其中n是石头的数量,k是士兵的数量。
可能会派上用场 其思想是运行深度优先搜索,计算从当前状态到结束的方法的数量,并存储此结果,然后在重复该状态时查找已计算的值 例如,从-#-#-
到达终点有2
种方法,因此,当我们通过-#-#-
到达终点时,存储这个结果,当我们通过-#-
到达终点时,我们可以简单地查找2
存储这些数据最简单(但远不是最有效)的方法是:
Map<Pair<Integer (Position1), Integer (Position2)>, Integer (Count)>
Map
更一般地说,您可以将该对
设置为列表
更有效的方法是使用位图,其中每个位对应于某个给定位置是否有士兵。所以
-#-#-
将对应于01010
,它可以简单地存储在int
中,作为十进制的10
——如果有64个以上的石头(即适合长的石头),您可以使用。我的解决方案在不到1秒的时间内运行10个位置。解决方案既快又脏,但算法是您应该感兴趣的,对吗
我的算法的思想是:
管理一组要计算的路径。从两名士兵都在最左边位置的路径开始
如果要计算的路径集不是空的,则选择任何路径并将其从集中移除
如果路径终止(两名士兵都在最正确的位置),打印路径。继续2
如果可能的话,通过移动首席士兵来扩展路径,并将其放入集合中
如果可能,通过移动尾兵来扩展路径,并将其放入集合中
就这样
public static void main(String[] args) {
List<Node> nodes = Node.newRootNode(10);
while (!nodes.isEmpty()) {
Node node = nodes.remove(0);
if (node.isLeaf()) node.printPath();
else {
if (node.headSoldierCanMove()) nodes.add(node.moveHeadSoldier());
if (node.tailSoldierCanMove()) nodes.add(node.moveTailSoldier());
}
}
}
static final class Node {
static List<Node> newRootNode(final int maxPos) {
return new ArrayList<Node>() {{
add(new Node(1, 2, maxPos, ""));
}};
}
private final int maxPos;
private final String path;
private int tailPos = 1;
private int headPos = tailPos + 1;
private Node(int tailPos, int headPos, int maxPos, String path) {
this.maxPos = maxPos;
this.tailPos = tailPos;
this.headPos = headPos;
this.path = addPath(path);
}
boolean tailSoldierCanMove() {
return tailPos < headPos - 1;
}
Node moveTailSoldier() {
return new Node(tailPos + 1, headPos, maxPos, path);
}
boolean headSoldierCanMove() {
return headPos < maxPos;
}
Node moveHeadSoldier() {
return new Node(tailPos, headPos + 1, maxPos, path);
}
void printPath() {
System.out.println(path);
}
boolean isLeaf() {
return headPos == maxPos && tailPos == headPos - 1;
}
private String addPath(String prefix) {
StringBuilder builder = new StringBuilder(prefix);
for (int pos = 1; pos <= maxPos; pos++) {
builder.append(tailPos == pos || headPos == pos ? "#" : "-");
}
return builder.append(" ").toString();
}
}
publicstaticvoidmain(字符串[]args){
List nodes=Node.newRootNode(10);
而(!nodes.isEmpty()){
节点=节点。删除(0);
if(node.isLeaf())node.printPath();
否则{
if(node.headSoldierCanMove())nodes.add(node.moveHeadSoldier());
if(node.tailSoldierCanMove())nodes.add(node.moveTailSoldier());
}
}
}
静态最终类节点{
静态列表newRootNode(最终int-maxPos){
返回新的ArrayList(){{
添加(新节点(1,2,maxPos,“”);
}};
}
私人最终int maxPos;
私有最终字符串路径;
私人int tailPos=1;
私人int headPos=tailPos+1;
专用节点(int tailPos、int headPos、int maxPos、字符串路径){
this.maxPos=maxPos;
this.tailPos=tailPos;
this.headPos=headPos;
this.path=addPath(path);
}
布尔tailSoldierCanMove(){
返回尾位置<头位置-1;
}
节点moveTailSoldier(){
返回新节点(tailPos+1、headPos、maxPos、path);
}
布尔headSoldierCanMove(){
返回headPos 对于(int pos=1;pos,最好使用组合数学来计算路径数
例如,假设有2名士兵和5个台阶
表示第一名士兵移动的距离y,第二名士兵移动的距离x
您试图计算从0,0到3,3的单调路径的数量,这样y永远不会大于x
这是一个众所周知的问题,答案由给出。在这种情况下,答案由n=3的加泰罗尼亚数给出,即5
当你有超过2名士兵时,你需要使用多维加泰罗尼亚数字。以下是有用的指南和公式:
T(m,n)=0!*1!*…*(n-1)!*(m*n)!/(m!*(m+1)!*…*(m+n-1)!)
你是在试图找到他们可以采取的方式还是有多少种方式?有多少种,只是数字如果我错了请纠正我,但我看不出运行深度优先搜索如何计算从当前状态获取的方式的数量