独轮车问题(C语言程序设计)

目录

 

问题描述

问题分析

运行程序输入的测试数据:

运行结果

代码实现

问题描述


独轮车的轮子上有5种颜色, 独轮车每走一格颜色变化一次, 并且独轮车只能往前推。 独轮车也可以在原地旋转,每走一格需要 一个单位的时间,每转90°需要一个单位的时间, 每转180°需要两个单位的时间。现给定一个 20x 20的迷宫,一个起点,一个终点和到达终点的颜色,问独轮车最少需要多少时间到达?

问题分析

先定义独轮车所在的行、列、当前颜色(5种)、方向(4 个),另外为了方便在结点中加上到达该点的最小步数,再用广度搜索返回目标结点的最小步数。

       本题包含一个测例。测试数据从第一行开始的20行每行内包含20个字符,表示迷宫的状态。其中区表示障碍物,‘.’表示空格(路);接下来的第21行输入以空格分隔的4个整数分别表示起点的坐标S(x.y)和两个整数轮子的颜色和开始的方向,第二行有以空格分隔的3个整数,表示终点的坐标T(x,y)和到达终点时轮子的颜色。

运行程序输入的测试数据:

XXXXXXXXXXXXXXXXXXXX

.....XXXX......X.XXX

X.........X.XX.....X

X.XXX.XX..X.XX.XXX.X

X.........X.XX.....X

X.XXX.XX..X.XX.XXX.X

.X.....XX.X.....X..X

X....X..X...X.X....X

...XXXX.X.XXX...XXXX

...........X.......X

XXXXXX....XXXXXX..XX

...........X.......X

.X.....XX.X.....X..X

XXXXXX....XXXXXXXX.X

X....X..X...X.X....X

...XXXX.X.XXX...XXXX

...........X.......X

XXX.X.XXXXX.XXXX.X.X

....X.XX....XXX.....

XXXX.....XX.........

运行结果

代码实现

#include<stdio.h>

struct cnode {
	int row;  //结点所在的行坐标
	int col;  //列坐标
	int color;   //颜色
	int direction; //方向
	int num;     //从起点到本结点的最小步数
};

struct cnode s;//start记录起始点信息
struct cnode t;//tail记录目标点信息
struct cnode open[200];//创建struct cnode类型的表
int head, tail, openlen = 200;//open表数据
int direct[4][2] = { {0,-1},{1,0},{0,1},{-1,0} };//向左,下,右,上四个方向转时,行列的增加值
int a[20][20];//记录迷宫路的状态
int n = 20;//n为迷宫边长
int b[20][20][5][4] ;//表示迷宫访问状态(0:未访问,1:已访问)


int search();//用广度搜索返回目标结点的最小步数
void readdate();//读入数据
void init();//初始化
struct cnode moveahead(struct cnode u);//返回u向前走一格得到的结点
int used(struct cnode v);//判断该结点是否是到达过的结点
void addtoopen(struct cnode v);//加入open表操作
int islegal(struct cnode v);//判断该结点是否是合法的结点(未越界且是空格)
int isaim(struct cnode v);//判断该结点是否是目标结点
struct cnode takeoutofopen();//从open表中取出一个结点,并将该节点在open表中删除
struct cnode turntoleft (struct cnode u);
struct cnode turntoright (struct cnode u);

int main()
{
	readdate();
	init();
	printf("独轮车最少需要%d个单位时间到达目标结点。\n", search());
	return 0;
}
int search()//用广度搜索返回目标结点的最小步数
{
	struct cnode u,v;
	while (head != tail)
	{
		u = takeoutofopen();		
		v = moveahead(u);//u向前走, 得到新结点v
		if (islegal(v))
		{
			if (isaim(v)) 
			{
				return (v.num);	
			}
			if (!used(v)) 
			{
				addtoopen(v);
			}
		}
		v = turntoleft(u);//u向左转,得到新结点v
		if (!used(v))
		{
			addtoopen(v);
		}
		v = turntoright(u);//u向右转,得到新结点v
		if (!used(v))
		{
			addtoopen(v);
		}
	}
}
void readdate()//读入数据
{
	char str[400];
	printf("请输入20*20的迷宫状态:(.表示空格,X表示有障碍物)\n");
	for (int i = 0; i < n; i++)
	{
		gets(str);
		for (int j = 0; j < n; j++)
		{
			if (str[j] == '.')  
			{
			 	a[i][j] = 0;	
			}
			else 
			{
				a[i][j] = 1;
			}
		}
	}
	printf("请输入起始结点信息(行、列、颜色、方向)\n");
	scanf("%d%d%d%d", &s.row, &s.col, &s.color, &s.direction);
	printf("请输入目标结点信息(行、列、颜色)\n");
	scanf("%d%d%d", &t.row, &t.col, &t.color);
}

void addtoopen(struct cnode v)
{
	open[tail++] = v;//把v放入open[tail],tail++
	tail = tail % openlen;//超出表的部分,更新原来的数据
	b[v.row][v.col][v.color][v.direction] = 1;//更新b数组 在v位置上的状态 为已到过
}
void init()
{
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			for (int k = 0; k < 5; k++)
			{
				for (int l = 0; l < 4; l++)
				{
					b[i][j][k][l] = 0;
				}
			}
		}
	}
	head = 0;
	tail = 0;
	addtoopen(s);//把起始点放入open表
}
struct cnode takeoutofopen()//从open表中取出一个结点,并将该节点在open表中删除
{
	struct cnode u;
	u = open[head++];
	head = head % openlen;
	return u;
}
struct cnode moveahead(struct cnode u)//返回u向前走一格得到的结点
{
	struct cnode v;
	v.row = u.row + direct[u.direction][0];//上下
	v.col = u.col + direct[u.direction][1];//左右
	v.color = (u.color + 1) % 5;//变一次颜色
	v.direction = u.direction;//方向不变
	v.num = u.num + 1;//步数+1,走了一步
	return v;
}
int isaim(struct cnode v)//判断该结点是否是目标结点
{
	if (v.row == t.row && v.col == t.col && v.color == t.color)
		return 1;
	else return 0;
}
int islegal(struct cnode v)//判断该结点是否是合法的结点(未越界且是空格)
{
	if (v.row < 0 || v.row >= n || v.col < 0 || v.col >= n)//越界了
		return 0;
	if (a[v.row][v.col] == 0)//结点未越界且是空格
		return 1;
	return 0;
}
int used(struct cnode v)//判断该结点是否是到达过的结点
{
	if (b[v.row][v.col][v.color][v.direction] == 0)  return 0;
	else return 1;
}
struct cnode turntoleft(struct cnode u)
{
	struct cnode v = u;
	v.direction = (v.direction + 1) % 4;
	v.num = v.num + 1;
	return v;
}
struct cnode turntoright(struct cnode u) 
{
	struct cnode v = u;
	v.direction = (v.direction + 3) % 4;
	v.num = v.num + 1;
	return v;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值