杭电1430康托 bfs(java)

举报
bigsai 发表于 2021/02/02 22:45:45 2021/02/02
【摘要】 魔板: Problem Description 在魔方风靡全球之后不久,Rubik先生发明了它的简化版——魔板。魔板由8个同样大小的方块组成,每个方块颜色均不相同,可用数字1-8分别表示。任一时刻魔板的状态可用方块的颜色序列表示:从魔板的左上角开始,按顺时针方向依次写下各方块的颜色代号,所得到的数字序列即可表示此时魔板的状态。例如,序列(1,2,3,4,5,6,7,8)...

魔板:
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

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。