c语言中dfs用pos做参数,使用DFS解决8-Puzzle

meriton - on..

6

好的,所以你的程序花费的时间比预期的要长.首先,我们要确定它是否陷入无限循环,或者只是缓慢.为此,让程序通过在主循环中添加以下内容来打印其进度:

int statesVisited = 0;

while (OPEN.empty() == false && STATE == false) {

statesVisited++;

System.out.println(statesVisited);

然后我们看到该程序每秒访问了几千个状态.由于我们的处理器每秒执行数十亿条指令,这意味着处理状态需要大约一百万条cpu指令.它不应该那么高,不是吗?那可能是什么导致了这个?

一般来说,我们现在使用分析器来测量代码中所占用的代码的哪一部分,但由于程序太短,我们可以先尝试猜测.我的第一个猜测是打印我们访问的每个州都可能非常昂贵.为了验证这一点,我们只打印每1000个状态:

while (OPEN.empty() == false && STATE == false) {

statesVisited++;

if (statesVisited % 1000 == 0) {

System.out.println(statesVisited);

}

我们改变了位置,我们注意到前5000个州在第二个国家被访问,所以印刷确实很重要.我们还注意到一些奇怪的事情:虽然前一个5000状态在一秒钟内被访问,但由于某种原因,程序似乎变得越来越慢.在访问的20000个州,大约需要一秒钟才能访问1000个州,并且情况会持续恶化.这是意料之外的,因为处理状态不应该变得越来越昂贵.所以我们知道循环中的一些操作变得越来越昂贵.让我们回顾一下我们的代码,以确定它可能是哪个操作.

无论集合的大小如何,推送和弹出都需要恒定的时间.但是你也使用Stack.search和LinkedList.contains.记录这两个操作都要求迭代整个堆栈或列表.那么,让我们输出这些集合的大小:

if (statesVisited % 1000 == 0) {

System.out.println(statesVisited);

System.out.println(OPEN.size());

System.out.println(CLOSED.size());

System.out.println();

}

等了一会儿后,我们看到:

40000

25947

39999

所以OPEN包含25000个元素,并且CLOSED接近40000个.这就解释了为什么处理状态会越来越慢.因此,我们希望选择具有更高效的包含操作的数据结构,例如a java.util.HashSet或java.util.LinkedHashSet(它是散列集和链表之间的混合,允许我们按照添加的顺序检索元素).这样做,我们得到:

public static LinkedHashSet OPEN = new LinkedHashSet();

public static HashSet CLOSED = new HashSet();

public static boolean STATE = false;

public static void main(String args[]) {

int statesVisited = 0;

String start = "123804765";

String goal = "281043765";

String X = "";

String temp = "";

OPEN.add(start);

while (OPEN.isEmpty() == false && STATE == false) {

X = OPEN.iterator().next();

OPEN.remove(X);

int pos = X.indexOf('0'); // get position of ZERO or EMPTY SPACE

if (X.equals(goal)) {

System.out.println("SUCCESS");

STATE = true;

} else {

// generate children

CLOSED.add(X);

temp = up(X, pos);

if (!(temp.equals("-1")))

OPEN.add(temp);

temp = left(X, pos);

if (!(temp.equals("-1")))

OPEN.add(temp);

temp = down(X, pos);

if (!(temp.equals("-1")))

OPEN.add(temp);

temp = right(X, pos);

if (!(temp.equals("-1")))

OPEN.add(temp);

}

}

}

/*

* MOVEMENT UP

*/

public static String up(String s, int p) {

String str = s;

if (!(p < 3)) {

char a = str.charAt(p - 3);

String newS = str.substring(0, p) + a + str.substring(p + 1);

str = newS.substring(0, (p - 3)) + '0' + newS.substring(p - 2);

}

// Eliminates child of X if its on OPEN or CLOSED

if (!OPEN.contains(str) && CLOSED.contains(str) == false)

return str;

else

return "-1";

}

/*

* MOVEMENT DOWN

*/

public static String down(String s, int p) {

String str = s;

if (!(p > 5)) {

char a = str.charAt(p + 3);

String newS = str.substring(0, p) + a + str.substring(p + 1);

str = newS.substring(0, (p + 3)) + '0' + newS.substring(p + 4);

}

// Eliminates child of X if its on OPEN or CLOSED

if (!OPEN.contains(str) && CLOSED.contains(str) == false)

return str;

else

return "-1";

}

/*

* MOVEMENT LEFT

*/

public static String left(String s, int p) {

String str = s;

if (p != 0 && p != 3 && p != 7) {

char a = str.charAt(p - 1);

String newS = str.substring(0, p) + a + str.substring(p + 1);

str = newS.substring(0, (p - 1)) + '0' + newS.substring(p);

}

// Eliminates child of X if its on OPEN or CLOSED

if (!OPEN.contains(str) && CLOSED.contains(str) == false)

return str;

else

return "-1";

}

/*

* MOVEMENT RIGHT

*/

public static String right(String s, int p) {

String str = s;

if (p != 2 && p != 5 && p != 8) {

char a = str.charAt(p + 1);

String newS = str.substring(0, p) + a + str.substring(p + 1);

str = newS.substring(0, (p + 1)) + '0' + newS.substring(p + 2);

}

// Eliminates child of X if its on OPEN or CLOSED

if (!OPEN.contains(str) && CLOSED.contains(str) == false)

return str;

else

return "-1";

}

public static void print(String s) {

System.out.println(s.substring(0, 3));

System.out.println(s.substring(3, 6));

System.out.println(s.substring(6, 9));

System.out.println();

}

几乎立即打印"SUCCESS".

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值