九宫重排—题解

历届试题 九宫重排  
时间限制:1.0s   内存限制:256.0MB
       
问题描述
  如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。

  我们把第一个图的局面记为:12345678.
  把第二个图的局面记为:123.46758
  显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
  本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
输入格式
  输入第一行包含九宫的初态,第二行包含九宫的终态。
输出格式
  输出最少的步数,如果不存在方案,则输出-1。
样例输入
12345678.
123.46758
样例输出
3
样例输入
13524678.
46758123.
样例输出
22

解题思路:   典型的 bfs , 最坏的情况 9!  最基本的bfs可以过评测。  后面附上双向BFS
1) 单向BFS
import java.util.LinkedList;
import java.util.Scanner;



public class Asist
{
	public static final int fac[] = {1,1,2,6,24,120,720,5040,40320,362880};
	public static final int move[][] = {{1,0},{-1,0},{0,1},{0,-1}};
	public static final int MAX = 1000000;
	public static  int step = -1;
    
	public static void main(String[] args)
	{
		Scanner sc = new Scanner(System.in);
		String str1 = sc.nextLine();
		String str2 = sc.nextLine();
	    Node start = new Node();
	    Node end = new Node();
	    for (int i = 0; i < str1.length(); i++)
	    {
	    	if (str1.charAt(i) == '.')
	    	{
	    		start.s = new StringBuffer(str1);
	    		start.s.replace(i, i+1, "0");
	    		start.index = i;
	    		start.step = 0;
	    		start.status = getHash(start.s.toString(), 9);
	    	}
	    	if (str2.charAt(i) == '.')
	    	{
	    		end.s = new StringBuffer(str2);
	    		end.s.replace(i, i+1, "0");
	    		end.index = i;
	    		end.step = 0;
	    		end.status = getHash(end.s.toString(), 9);
	    	}
	    }
	    if (str1.equals(str2)) System.out.println(0);
	    else
	    {
	    	bfs(start, end);
	    	System.out.println(step);
	    }
	}

	private static void bfs(Node start, Node end)
	{
        boolean vis[] = new boolean[MAX];
        LinkedList<Node> list = new LinkedList<Node>();
        Node cur, next;
        cur = getNode(start);
        list.add(cur);
        
        while(!list.isEmpty())
        {
        	cur = list.pop();
            int x = cur.index / 3;
            int y = cur.index % 3;
            for (int i = 0; i < 4; i++)
            {
               int tx = x + move[i][0];
               int ty = y + move[i][1];
               if (tx > 2 || tx < 0 || ty > 2 || ty < 0) continue;
               next = getNode(cur);
               next.index = tx * 3 + ty;
               next.s.replace(cur.index, cur.index+1, cur.s.charAt(next.index)+"");
               next.s.replace(next.index, next.index+1, "0");
               next.step++;
               next.status = getHash(next.s.toString(), 9);
               
               if (next.status == end.status)
               {
            	   step = next.step; return;
               }
               if (!vis[next.status])
               {
            	   vis[next.status] = true;
            	   list.add(next);
               }
            }
        }
	}

	// 对象的拷贝
	private static Node getNode(Node start)
	{
       Node node = new Node();
       node.s = new StringBuffer(start.s.toString());
       node.index = start.index;
       node.step = start.step;
       node.status = start.status;
       return node;
	}

	private static int getHash(String start, int len)
	{
		int sum = 0;
		for (int i = 0; i < len; i++)
		{
           int count = 0;
           for (int j = i + 1; j < len; j++)
             if (start.charAt(i) > start.charAt(j)) count++;
           sum += count * fac[len-i-1];
		}
		return sum+1;
	}    
} 
class Node
{
	StringBuffer s;  // 记录
	int index;       // 空格
	int step;        // 步数
	int status;      // Hash地址
	
}

2)双向BFS
import java.util.LinkedList;
import java.util.Scanner;





/**
 * 
 *  九宫重排
 *   
 *  双向bfs解法
 * @author Xujing
 *
 */
public class Main1
{
	public static final int fac[] = {1,1,2,6,24,120,720,5040,40320,362880};
	public static final int move[][] = {{1,0},{-1,0},{0,1},{0,-1}};
	public static final int MAX = 500000;
	public static int step = 0;
	public static void main(String[] args)
	{
		Scanner sc = new Scanner(System.in);
        String str1 = sc.nextLine();
        String str2 = sc.nextLine();
        sc.close();
        Node start = new Node();
        start.s = new StringBuffer(str1);
        start.index = start.s.indexOf(".");
        start.status = getHash(str1);
        start.step = 0;
        Node end = new Node();
        end.s = new StringBuffer(str2);
        end.index = end.s.indexOf(".");
        end.status = getHash(str2);
        end.step = 0;
        long t = System.nanoTime();
        if (start.status == end.status) System.out.println(0);
        else{
        	bfs(start, end);
        	System.out.println(step);
        }
 		System.out.println(System.nanoTime() - t + "   ns");
	}
	private static void bfs(Node start, Node end)
	{
		int vis1[] = new int[MAX];
		int vis2[] = new int[MAX];
		LinkedList<Node> list1 = new LinkedList<Node>();
		LinkedList<Node> list2 = new LinkedList<Node>();
	    Node cur1,next1, cur2, next2;
	    cur1 = getObject(start);
	    cur2 = getObject(end);
	    list1.add(cur1);
	    list2.add(cur2);
	    while(!list1.isEmpty() && !list2.isEmpty())
	    {
	    	// 起始状态bfs
	    	cur1 = list1.pop();
	    	int x1 = cur1.index / 3;
	    	int y1 = cur1.index % 3;
	    	for (int i = 0; i < 4; i++)
	    	{
	    		int tx1 = x1 + move[i][0];
	    		int ty1 = y1 + move[i][1];
	    		if (tx1 > 2|| tx1 < 0 || ty1 > 2 || ty1 < 0) continue;
	    		next1 = getObject(cur1);
	    		next1.index = tx1 * 3 + ty1;
	    		next1.s.replace(cur1.index, cur1.index+1, cur1.s.charAt(next1.index)+"");
	    		next1.s.replace(next1.index, next1.index+1, ".");
	    		next1.status = getHash(next1.s.toString());
	    		next1.step++;
	    		if (0==vis1[next1.status])
	    		{
	    			vis1[next1.status] = next1.step;
	    			list1.add(next1);
	    		}
	    		if (vis1[next1.status]!=0 && vis2[next1.status]!=0)
	    		{
	    			step = vis1[next1.status] + vis2[next1.status]; return;
	    		}
	    	}
	    	// 目标状态bfs
	    	cur2 = list2.pop();
	    	int x2 = cur2.index / 3;
	    	int y2 = cur2.index % 3;
	    	for (int i = 0; i < 4; i++)
	    	{
	    		int tx2 = x2 + move[i][0];
	    		int ty2 = y2 + move[i][1];
	    		if (tx2 > 2|| tx2 < 0 || ty2 > 2 || ty2 < 0) continue;
	    		next2 = getObject(cur2);
	    		next2.index = tx2 * 3 + ty2;
	    		next2.s.replace(cur2.index, cur2.index+1, cur2.s.charAt(next2.index)+"");
	    		next2.s.replace(next2.index, next2.index+1, ".");
	    		next2.status = getHash(next2.s.toString());
	    		next2.step++;
	    		if (0==vis2[next2.status])
	    		{
	    			vis2[next2.status] = next2.step;
	    			list2.add(next2);
	    		}
	    		
	    		if (vis1[next2.status]!=0 && vis2[next2.status]!=0)
	    		{
	    			step = vis1[next2.status] + vis2[next2.status]; return;
	    		}
	    	}
	    	
	    }
	}
	private static Node getObject(Node start)
	{
		Node node = new Node();
		node.s = new StringBuffer(start.s.toString());
		node.index = start.index;
		node.status = start.status;
		node.step = start.step;
		return node;
	}
	private static int getHash(String str)
	{
		int sum = 0;
		for (int i = 0; i < str.length(); i++)
		{
			int count = 0;
			for (int j = i+1; j < str.length(); j++)
				if (str.charAt(i)>str.charAt(j))count++;
			sum += count*fac[str.length()-i-1];
		}
		return sum+1;
	}
}
class Node
{
	StringBuffer s;   // 路径
	int index;        // 空格
	int status;       // Hash值
	int step;         // 步数
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值