蓝桥杯—第八届—A组—第二题—跳蚱蜢 {C语言}=====【可调试】

如图 p1.png 所示: 
有9只盘子,排成1个圆圈。
其中8只盘子内装着8只蚱蜢,有一个是空盘。
我们把这些蚱蜢顺时针编号为 1~8

每只蚱蜢都可以跳到相邻的空盘中,
也可以再用点力,越过一个相邻的蚱蜢跳到空盘中。

请你计算一下,如果要使得蚱蜢们的队形改为按照逆时针排列,
并且保持空盘的位置不变(也就是1-8换位,2-7换位,...),至少要经过多少次跳跃?

注意:要求提交的是一个整数,请不要填写任何多余内容或说明文字。

这个题的思路是bfs,我本来用的dfs怎么都不对,
而且我写的这个也不是正确答案,因为6以下的数都行,如果超过6位数就不行了,应该是内存过大
目前还不知道怎么解决: 见谅

语言是C语言,

圆圈用的 循环队列模拟,那个求0的位置和分解的函数可以只用一个就行,写麻烦了,每一个函数后边都谢了注释功能是什么,英语不好请见谅,使用的拼音,希望能帮助你们一点点

这个题是求的最短路径,我把每次怎么执行的步骤存到了,ma数组中,这样就可以用一个小范围的数据调试,清除每一步的步骤
这个题和八数码有点相似,都是bfs,我学的还不够好,大神看到请指点指点

代码有点多,希望仔细看看,是C语言,写的还行,这个题困扰了我两三天

因为我做题一直是bfs,还好把我稍微看看了数据结构

虽然不是严蔚敏,严蔚敏这本书挺好的,里面有算法

下面是代码

#include<stdio.h>
#include<string.h>
#define N 6//位数 
#define M 54321//需要转动的状态 
#define MM 12345 //初始状态     
int a[9] = {0,1,2,3,4,5,6,7,8}; //这个是总共有八个蚱蜢,
//但是我做的超过了留个就不行了,应该是超时了,不知道怎么弄 
int max[5000000] ={0};//判断重复 
int ma[500][2] = {0};//存储路径 
int way[500]; //变化后的状态 
int F = 0,P = 0;//第一个记录max的位置,第二个记录是否有重复 
int fenjie(int k)//把每一位 N-1 位数 分解在a数组中,方便交换 
{
	int i,j;
	for(i = N - 1; i >= 0;i--)
	{
		a[i] = k % 10;
		k /= 10;
		if(a[i] == 0)
			j = i; 
	}
	return j; 
}
int weizhi0(int n)//求0的位置   
{
	int k = n;
	int i = N;
	while(k)
	{
		i--;
		if(k % 10 == 0)
			return i;
		k/=10;
	}
}
void swap(int i,int j)//交换 
{
	int t = a[i];
	a[i] = a[j];
	a[j] = t;
}
int sum()//求和 
{
	int i,s = 0,l = 1;
	for(i = N-1; i >= 0; i--)
	{
		s += l*a[i];
		l *= 10;
	}
	return s;
}

int f(int n)//n:总共执行了多少次 
{
	int k;
	int i = fenjie(max[n]); 
	int one = i - 1,two = i - 2;
	int one1 = (i+1)%N,two1 = (i+2)%N;
	
	if(P == 0)//没有相等的 
	{
		
		if(one < 0)
			one = N + one;
		if(two < 0)
			two = N + two;
		
		swap(i,two1);
		k = sum(); 
		max[++F] = k;
		if(k == M){
			P = 1; 
		}
		swap(i,two1);

		swap(i,one1); 
		k = sum(); 
		max[++F] = k;
		if(k == M){
			P = 1; 
		}
		swap(i,one1);
		 
		swap(i,one);
		k = sum(); 
		max[++F] = k;
		if(k == M){
			P = 1; 
		}
		swap(i,one);
		
		swap(i,two); 
		k = sum(); 
		max[++F] = k;
		if(k == M){
			P = 1; 
		}
		swap(i,two);
		
		f(n+1);//递归 
	}
}
int shuchubuzhou(int i)// 给way数组赋值步骤 
{
	int j,k,s = 0;
	while(i)
	{
		j = weizhi0(way[i]);
		k = weizhi0(way[i-1]);
		ma[s][0] = k;
		ma[s][1] = j;
		s++;
		i--;
	}
	ma[s][0] = 0;
	ma[s][1] = k;
}
int printff(int s)//输出步骤 
{
	int j,i = 1,x = 1;
	
	while(i++<N)
	{
		x *= 10;
	}
	
	way[0] = M;
	printf("初始\t   0%d  下标\n\n",MM);
	for(j = 1,i = s-1; i >= 0; i--,j++)
	{
		printf("第%d步:",j);
		if(way[i] / x == 0)printf("     0%d  ",way[i]);
		else printf("     %d  ",way[i]);
		printf("%d->%d\n",ma[j][1],ma[j][0]);
	}
	printf("结束\n");
	printf("\n总共%d步\n",s);
} 
int wayfuzhi()//给way数组赋值 ,每次变换后的数值 
{
	int s = 0;
	while(F)
	{
		s++;
		F = (F - 1)/4;
		way[s] = max[F];
	}
	return s;
}
int main()
{
	
	int s;
	max[0] = MM;//给第一个位置赋值 
	
	f(0);//调用函数 
	
	//printf("%d\n",F);//输出在bfs中的结束表格 
	
	s = wayfuzhi();//给way进行赋值 
	
	shuchubuzhou(s+1);//把步骤赋值到way数组中 
	
	printff(s);//输出步骤
}

猜你喜欢

转载自blog.csdn.net/weixin_42295018/article/details/88532767