chapter05-Hike on a Graph(POJ 2415)

Hike on a Graph


Time Limit: 2 Seconds      Memory Limit: 65536 KB


"Hike on a Graph" is a game that is playedon a board on which an undirected graph is drawn. The graph is complete and hasall loops, i.e. for any two locations there is exactly one arrow between them.The arrows are coloured. There are three players, and each of them has a piece.At the beginning of the game, the three pieces are in fixed locations on thegraph. In turn, the players may do a move. A move consists of moving one's ownpiece along an arrow to a new location on the board. The following constraintis imposed on this: the piece may only be moved along arrows of the same colouras the arrow between the two opponents' pieces.

In the sixties ("make love not war") aone-person variant of the game emerged. In this variant one person moves allthe three pieces, not necessarily one after the other, but of course only oneat a time. Goal of this game is to get all pieces onto the same location, usingas few moves as possible. Find out the smallest number of moves that isnecessary to get all three pieces onto the same location, for a given boardlayout and starting positions.

Input Specification

The input file contains several test cases. Each testcase starts with the number n. Input is terminated by n=0.Otherwise, 1<=n<=50. Then follow three integers p1,p2, p3 with 1<=pi<=n denotingthe starting locations of the game pieces. The colours of the arrows are givennext as a m×m matrix of whitespace-separated lower-case letters. Theelement mij denotes the colour of the arrow between thelocations i and j. Since the graph is undirected, you can assumethe matrix to be symmetrical.

Output Specification

For each test case output on a single line the minimumnumber of moves required to get all three pieces onto the same location, or theword "impossible" if that is not possible for the given board andstarting locations.

Sample Input

3 1 2 3

r b r

b b b

r b r

2 1 2 2

y g

g y

0

ample Output

2

Impossible



题目大意:

         这道题还真不是那么好读懂,看了半天。。晕。。。

讲的就是一个完全无向图(任意两点都相连,也都有自连边),顶点个数为n(1<=n<=50);每条边都有一种颜色(用小写字母表示),现在有三颗棋子(固定有且只有三个),他们的初始位置分别为p1,p2,p3,现在要求移动这些棋子,使其能够移动三颗到达同一个点的最小步数?棋子能够移动的条件的,当棋子要移动的位置的边的颜色与另外两颗棋子的边的颜色一样;(注意:自连边的目的就是当两颗棋子处于一个位置时,他们之间的边就是自连边哈)

 

分析:利用穷举的

方法,遍历他们可以到达的点的任意组合;

用广度搜索的方法:有队列Q

一次计算的内容包括p1,p2,p3,

将p1能够到达的所有位置和p2,p3一起存入队列;

将p2能够到达的所有位置和p1,p3一起存入队列;

将p3能够到达的所有位置和p1,p2一起存入队列;

(当然以上所有的步数都仅仅算一次,还要判断相关条件);

因此需要三维数组dis[][][]来存储这些组合的步数;

已知dis[p1][p2][p3]=0

 

代码如下:

import java.io.BufferedInputStream;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Scanner;

public class Main {
	
	private int[][][] dis;
	private char[][] color;
	
	private static int p1;
	private static int p2;
	private static int p3;
	
	public Main(int n){
		dis = new int[n][n][n];
		color = new char[n][n];
		
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				Arrays.fill(dis[i][j], -1);
			}
		}
	}
	
	public int getCountSum(){
	
		LinkedList<node> llist = new LinkedList<node>();
		node vernode;
		vernode = new node(p1,p2,p3);
		
		if(vernode.isRightAns()){
			return 0;
		}
		
		llist.add(vernode);
		dis[p1][p2][p3] = 0;
		
		//因为是广度遍历,所以得到的第一个相等的数必然是最小步数的数
		while(llist.size()>0){
			int x,y,z;
			vernode = llist.remove();
			
			x = vernode.x;
			y = vernode.y;
			z = vernode.z;
			//移动第一个棋子 p1
			for(int i=0;i<dis.length;i++){
				if(color[x][i] == color[y][z] && x!=i && dis[i][y][z] == -1){
					dis[i][y][z] = dis[x][y][z]+1;
					vernode = new node(i,y,z);
					if(vernode.isRightAns()){
						return dis[i][y][z];
					}
					llist.add(vernode);
				}
			}
			//移动第一个棋子 p2
			for(int i=0;i<dis.length;i++){
				if(color[y][i] == color[x][z] && y!=i && dis[x][i][z] == -1){
					dis[x][i][z] = dis[x][y][z]+1;
					vernode = new node(x,i,z);
					if(vernode.isRightAns()){
						return dis[x][i][z];
					}
					llist.add(vernode);
				}
			}
			
			//移动第一个棋子 p3
			for(int i=0;i<dis.length;i++){
				if(color[z][i] == color[x][y] && z!=i && dis[x][y][i] == -1){
					dis[x][y][i] = dis[x][y][z]+1;
					vernode = new node(x,y,i);
					if(vernode.isRightAns()){
						return dis[x][y][i];
					}
					llist.add(vernode);
				}
			}
		}
		
		return -1;
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int n;
		Main ma;
		int temp;
		Scanner cin = new Scanner(new BufferedInputStream(System.in));

		while((n= cin.nextInt()) != 0){
			ma = new Main(n);
			p1 = cin.nextInt()-1;
			p2 = cin.nextInt()-1;
			p3 = cin.nextInt()-1;
			
			for(int i =0;i<n;i++){
				for(int j=0;j<n;j++){
					ma.color[i][j] = cin.next().charAt(0);
				}
			}
			
			if((temp =ma.getCountSum() )== -1){
				System.out.println("impossible");
			}else{
				System.out.println(temp);
			}
		}
	}
	class node{
		public int x, y, z;
		public node(int x,int y,int z){
			this.x = x;
			this.y = y;
			this.z = z;
		}
		public boolean isRightAns(){
			if(x == y && y ==z){
				return true;
			}
			return false;
		}
	}

}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值