杭电1430康托 bfs(java)
魔板:
 Problem Description
 在魔方风靡全球之后不久,Rubik先生发明了它的简化版——魔板。魔板由8个同样大小的方块组成,每个方块颜色均不相同,可用数字1-8分别表示。任一时刻魔板的状态可用方块的颜色序列表示:从魔板的左上角开始,按顺时针方向依次写下各方块的颜色代号,所得到的数字序列即可表示此时魔板的状态。例如,序列(1,2,3,4,5,6,7,8)表示魔板状态为:
 1 2 3 4
 8 7 6 5
 对于魔板,可施加三种不同的操作,具体操作方法如下:
 A: 上下两行互换,如上图可变换为状态87654321
 B: 每行同时循环右移一格,如上图可变换为41236785
 C: 中间4个方块顺时针旋转一格,如上图可变换为17245368
给你魔板的初始状态与目标状态,请给出由初态到目态变换数最少的变换步骤,若有多种变换方案则取字典序最小的那种。
Input
 每组测试数据包括两行,分别代表魔板的初态与目态。
Output
 对每组测试数据输出满足题意的变换步骤。
Sample Input
 12345678
 17245368
 12345678
 82754631
Sample Output
 C
 AC
 分析核心:映射,bfs,康托(康托只是一个工具)
 1:刚开始的做法:把没输入的两行当作字符串,写出函数ABC的操作过程,然后每输入一个数就把他当作初态然后运行bfs。输出结果。当然,肯定是要标记进行bfs的。我就建立了boolean【88888888】数组对其标记,结果:wa
 2:后来参考了别人的做法:首先把字符串的处理变成char【】数组的处理。我发现别人都用康托展开。后来想了一下,这八个数的排列是有顺序并且没有重复的,总共就8!种情况,我用了88888888数组明显造成资源浪费。然后就学习了下康托展开。对于康托,只是一种表示的工具,可以看作是一种巧妙的数据结构,但是不是算法。附上康托展开实现
	static int kangtuo(char a[])//转化为康托展开的值
	{
	int jiecheng[]= {1,1,2,6,24,120,720,5040};
		int m=0,n=0;
		for(int i=0;i<8;i )
		{ m=0; for(int j=i 1;j<8;j ) { if(a[i]>a[j])m ; } n =m*jiecheng[7-i];
		}
		return n; }
  
 - 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
这样就可以用40321个数表示所有能出现的情况,而不需要88888888个。但是结果还是wa
3:请教学长之后,想到了用映射。就是跑一遍bfs,而不是跑多遍bfs,一遍bfs记录所有的结果,你或许会问初态不一样,终态不一样怎么办,你要转化,把所有的初态转化成12245678,所有终态转化为对应数字,直接输入对应的记录过的结果,简而言之就是我后面输入输出,我只在意他位置的变化,而不是数字的变化,举个简单例子,如果输入的是321,213,你可以看到第一个数3跑到第三位上,2跑到第一位上,1跑到第二位上,(这里就是把三看成1,把2看成2,把1看成3)他的执行步骤其实和123跑到231,看看两组数组的位置是否对应一样。理解这个就可以了。
 附上代码如下:
import java.util.ArrayDeque;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class 杭电1430 {
	static int jiecheng[]= {1,1,2,6,24,120,720,5040};
	public static void main(String[] args) { Scanner sc=new Scanner(System.in); int jud[]=new int[40321]; String path[]=new String[40321]; char start[]= {'1','2','3','4','5','6','7','8'}; path[kangtuo(start)]="";//初始第一个数组元素是""而不是null 
 	Queueq1=new ArrayDeque();
 	q1.add(start); while(!q1.isEmpty())
 	{ char t2[]=q1.poll(); //去头并返回 int exam=kangtuo(t2);//当前的康托展开值 jud[exam]=1; { char p1[]=a(t2);int kang=kangtuo(p1);//分别走三部并且判断是否可走 		 if(jud[kang]==0) {q1.add(p1);path[kang]=path[exam] 'A';jud[kang]=1; } char p2[]=b(t2); kang=kangtuo(p2); if(jud[kang]==0) {q1.add(p2);path[kang]=path[exam] 'B'; jud[kang]=1;} char p3[]=c(t2); kang=kangtuo(p3); if(jud[kang]==0) {q1.add(p3);path[kang]=path[exam] 'C';jud[kang]=1; } } } 
 while(sc.hasNextLine())
 { String c=sc.nextLine();//初始状态 	
 	String d=sc.nextLine();//结束状态 
 	char c1[]=c.toCharArray();
 char d1[]=d.toCharArray();//转化为字符数组
 d1= zhuanhua(c1,d1);
 System.out.println(path[kangtuo(d1)]); }
	}
	private static char[] zhuanhua(char[] c1, char[] d1) {	
	for(int i=0;i<8;i )
	{
		for(int j=0;j<8;j )
		{if(d1[i]==c1[j]) {d1[i]=(char) (j 1 '0');break;}}
	}
	return d1; }
	static int kangtuo(char a[])//转化为康托展开的值
	{
		int m=0,n=0;
		for(int i=0;i<8;i )
		{ m=0; for(int j=i 1;j<8;j ) { if(a[i]>a[j])m ; } n =m*jiecheng[7-i];
		}
		return n; }
 static void swap(char a[],int b,int c)
	{ char tem=a[b];
		a[b]=a[c];
		a[c]=tem; }	
private	static char[] a(char b[])//a的实现方法
	{
		char a[]=b.clone();//赋值b数组不改变b数组
		swap(a,0,7);
		swap(a,1,6);
		swap(a,2,5);
		swap(a,3,4);
		return a;
	}
	static char[] b(char b[])
	{
		char a[]=b.clone();
		swap(a,3,2);
		swap(a,2,1);
		swap(a,1,0);
		swap(a,4,5);
		swap(a,5,6);
		swap(a,6,7);
		return a;
	}
	static char[] c(char b[])
	{
		char a[]=b.clone();
		swap(a,1,6);
		swap(a,2,6);
		swap(a,5,6); return a;
	}		
}
  
 - 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
康托只是一种工具,其中映射的道理,减少bfs的次数。才是最重要的。
文章来源: bigsai.blog.csdn.net,作者:Big sai,版权归原作者所有,如需转载,请联系作者。
原文链接:bigsai.blog.csdn.net/article/details/79914365
- 点赞
- 收藏
- 关注作者
 
             
           
评论(0)