算法题之迷宫中任意位置走任意长度的所有路径查询【原创题,非官方题目】

迷宫大家都知道是可以用通过dfs(深度优先算法)进行解决,现在问题如下:小明参加了一个迷宫游戏,这个游戏有这样一个规则:小明只能向上下左右方向任意走n步(可以走回头路),现在需要知道这任意的n步所能覆盖的点的范围和这n步所有的路径

基本原理

经过推理,任意走n步(可以走回头路)有一个规律,那就是所有点构成的图形是一个旋转45度的正方形,如下图所示
在这里插入图片描述
并且从图上可以发现一个规律就是不管从哪个点走,走n步后走到的点的个数为(n+1)^2, 经过测试这个规律是正确的。
那么现在问题又来了,如何去获取这些点的坐标和所有到达的路径呢?

获取点的坐标【难度:简单】

思路如下:

  1. 输入坐标(x,y)和要走的步数
  2. 利用递归实现上下左右四个方向随意走动的功能,每走一步步数减一
  3. 当步数为0时输出当前的点的坐标

代码如下:

/**
	 * 深度遍历某一个位置走nbStep后的点坐标
	 * @param x  初始时的横坐标,注意这里为二维数组的第二维度
	 * @param y  初始时的纵坐标,注意这里为二维数组的第一维度
	 * @param nbStep 第几步
	 * direction 方向 ( 规定 1- 向右,2-向下, 3-向左,4-向上)
	 * @return 所到达的点坐标集合
	 */
	public static List<String> DFSResult(
			int x, int y, int nbStep
	) {
		List<String> result = DFSResult(
				x, y, nbStep, new ArrayList<String>()
		);
		return result;
	}
	private static List<String> DFSResult(
			int x, int y, int nbStep, List<String> result
	) {
		if (nbStep == 0) {
			String res = "(" + x + "," + y + ")";
			if (!result.contains(res)) {
				result.add(res);
			}
			return result;
		}
		int nextX = 0, nextY = 0;
		for (int direction = 1; direction < 5; direction++) {
			switch(direction) {
			case 1: nextX = x + 1; nextY = y; break;
			case 2: nextX = x; nextY = y + 1; break;
			case 3: nextX = x - 1; nextY = y; break;
			case 4: nextX = x; nextY = y - 1; break;
			}
			DFSResult(nextX,nextY, nbStep - 1, result);
		}
		return result;
	}

输入:
原点坐标(4,4)
要走的步数 2

输出:

(6,4)
(5,5)
(4,4)
(5,3)
(4,6)
(3,5)
(2,4)
(3,3)
(4,2)

获取所有到达的路径【难度:困难】

思路:

  1. 利用stack(栈)的先进后出原理存储每个路径上的点
  2. 每次走一步前将要到达的点存入stack中
  3. 当前节点上下左右都递归完毕后就返回前一节点继续后续的递归,这里要pop一下

代码如下:

/**
	 * 深度遍历某一个位置走nbStep后的路径
	 * @param x  初始时的横坐标,注意这里为二维数组的第二维度
	 * @param y  初始时的纵坐标,注意这里为二维数组的第一维度
	 * @param nbStep 第几步
	 * direction 方向 ( 规定 1- 向右,2-向下, 3-向左,4-向上)
	 */
	//node 为路径上的节点
	private class Node{
		int x;
		int y;
		public int getX() {
			return x;
		}
		public void setX(int x) {
			this.x = x;
		}
		public int getY() {
			return y;
		}
		public void setY(int y) {
			this.y = y;
		}
		public Node(int x, int y) {
			super();
			this.x = x;
			this.y = y;
		}
		@Override
		public String toString() {
			return "Node [x=" + x + ", y=" + y + "]";
		}
		
	}
	//用栈存放路径的节点
	private static Stack<Node> stackNode = new Stack<>();
	private static List<String> DFSRoute(
			int x, int y, int nbStep
	) {
		List<String> res = new ArrayList<>(); // 返回结果
		// 如果是最后一个位置就返回路径
		if (nbStep == 0) {
			StringBuilder sb = new StringBuilder();
			for (int i = 0; i < stackNode.size(); i++) {
				Node node = stackNode.get(i);
				if (i == stackNode.size() - 1) {
					sb.append("(" + node.getX() + "," + node.getY() + ")");
				} else {
					sb.append("(" + node.getX() + "," + node.getY() + ") => ");
				}
			}
			res.add(sb.toString());		
			stackNode.pop(); //弹出最后一个元素
			return res;
		}
		Node node = new Path().new Node(x, y);
		if (stackNode.size() == 0) {
			stackNode.push(node);
		}
		int nextX = 0, nextY = 0;
		// 前后左右走一遍
		for (int direction = 1; direction < 5; direction++) {
			switch(direction) {
			case 1: nextX = x + 1; nextY = y; break;
			case 2: nextX = x; nextY = y + 1; break;
			case 3: nextX = x - 1; nextY = y; break;
			case 4: nextX = x; nextY = y - 1; break;
			}
			// 将将要走上的点存入stack中
			Node node1 = new Path().new Node(nextX, nextY);
			stackNode.push(node1);
			//开启下一个递归,将结果保存在res中
			res.addAll(DFSRoute(nextX,nextY, nbStep - 1));
		}
		// 关键点:每次前后左右都走了一遍后就返回前一节点
		stackNode.pop();
		return res;
	}

输入:
原点坐标(4,4)
要走的步数 2

输出:

(4,4) => (5,4) => (6,4)
(4,4) => (5,4) => (5,5)
(4,4) => (5,4) => (4,4)
(4,4) => (5,4) => (5,3)
(4,4) => (4,5) => (5,5)
(4,4) => (4,5) => (4,6)
(4,4) => (4,5) => (3,5)
(4,4) => (4,5) => (4,4)
(4,4) => (3,4) => (4,4)
(4,4) => (3,4) => (3,5)
(4,4) => (3,4) => (2,4)
(4,4) => (3,4) => (3,3)
(4,4) => (4,3) => (5,3)
(4,4) => (4,3) => (4,4)
(4,4) => (4,3) => (3,3)
(4,4) => (4,3) => (4,2)

写的不足之处欢迎指出,也欢迎联系我qq:271527068

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
#include #include #define N1 9 #define N2 8 #define T N1*N2 #define M 4 char B[N1+1][N2+1]; int count=0; //记录路径条数 typedef struct node1 { int a1; int a2; }find,direct[M+1]; typedef struct { int b1; int b2; int id; }site; typedef struct //顺序栈 { site ht[T]; int top; }Stack; void Push(Stack *s,int a,int b) { s->top++; s->ht[s->top].b1=a; s->ht[s->top].b2=b; } void Gettop(Stack * s,int *a,int *b) { *a=s->ht[s->top].b1; *b=s->ht[s->top].b2; } void create(char *a) //从文件读出迷宫(正确) { int i=0,j=0,p=1; char x; FILE *fp; fp=fopen("in.txt","r"); if(fp==NULL) { printf("文件不能打开!\n"); exit(0); } x=fgetc(fp); while(x!=EOF) { if(x=='0') { i++; a[i]=x; } if(x=='1') { i++; a[i]=x; } x=fgetc(fp); } printf(" ~~~~~~~生成迷宫~~~~~~~\n"); x=fgetc(fp); while(p<=T) //用二维数组b记录迷宫每个位置是否可行 { for(i=1;i<=N1;i++) for(j=1;j<=N2;j++) { B[i][j]=a[p]; p++; } } printf(" "); printf("■■■■■■■■■■■■\n"); printf(" ■"); printf(" ■\n"); for(i=1;i<=N1;i++) { printf(" "); printf("■ "); for(j=1;jht[s1->top].id=id; B[x][y]='*'; while(s1->top>0) { Gettop(s1,&x,&y); id=s1->ht[s1->top].id; if(x==B1&&y==B2) { count++; fprintf(fp,"%d%c%c",count,':',' '); printf("第 %d 条路径(长度为%d):\n",count,s1->top); s1->ht[s1->top].id=0; for(i=1;itop;i++) { printf("(%d,%d,%d)->",s1->ht[i].b1,s1->ht[i].b2,s1->ht[i].id); fprintf(fp,"%c%d%c%d%c%d%c%c",'(',s1->ht[i].b1,',',s1->ht[i].b2,',',s1->ht[i].id,')',' '); if(i==0) fprintf(fp,"%c%c%c%c",'\n',' ',' ',' '); if(i%8==0) printf("\n"); } fprintf(fp,"%c",'\n'); printf("结束!\n\n"); if(s1->toptop=s1->top; min=s1->top; for(i=1;itop;i++) s2->ht[i]=s1->ht[i]; } B[x][y]='0'; s1->top--; //退栈(s1->top--) Gettop(s1,&x,&y); id=s1->ht[s1->top].id; } fun=0; while(idht[s1->top].b1; y=s1->ht[s1->top].b2; x=x+p[id].a1; y=y+p[id].a2; if(x==0||y==0||x>N1||y>N2) continue; if(B[x][y]=='0') { fun=1; break; } } if(fun==1) //找到通路 { s1->ht[s1->top].id=id; Push(s1,x,y); B[x][y]='*'; s1->ht[s1->top].id=0; } else { x=s1->ht[s1->top].b1; y=s1->ht[s1->top].b2; B[x][y]='0'; s1->top--; } } if(count==0) printf(" 无路径!\n"); else { printf("\n\n\n "); printf("所有路径已存储在文件%s ,请去查找!\n\n",filename); } return 1; } void Print(Stack *s2,char filename[]) { int i; FILE *fp; fp=fopen(filename,"a+"); if(fp==NULL) { printf("文件不能打开!\n"); exit(0); } if(count!=0) { fprintf(fp,"%s","最短路径为:"); fprintf(fp,"%c",'\n'); printf(" "); printf("%s\n","**********最短路径**********\n"); for(i=1;itop;i++) { printf("(%d,%d,%d) ->",s2->ht[i].b1,s2->ht[i].b2,s2->ht[i].id); fprintf(fp,"%c%d%c%d%c%d%c%c",'(',s2->ht[i].b1,',',s2->ht[i].b2,',',s2->ht[i].id,')',' '); if(i==0) fprintf(fp,"%c",'\n'); if(i%7==0) printf("\n"); } fprintf(fp,"%c",'\n'); printf("结束!\n"); printf("(最短路径长度: %d)\n",s2->top); } } void main() //主函数 { char a[T+1]; //二维数组b记录迷宫的每个位置 char filename1[20],filename2[20]; int x1,x2,y1,y2,k; Stack *s1,*s2; direct f1; f1[1].a1=0; f1[1].a2=1; //判断方向(右) f1[2].a1=1; f1[2].a2=0; //(下) f1[3].a1=0; f1[3].a2=-1; //(左) f1[4].a1=-1; f1[4].a2=0; //(上) s1=(Stack *)malloc(sizeof(Stack)); s2=(Stack *)malloc(sizeof(Stack)); s1->top=0; //指向栈顶(初始化栈) s2->top=0; create(a); printf("\n\n "); printf("请输入入口坐标: "); scanf("%d%d",&x1,&x2); printf(" "); printf("请输入出口坐标: "); scanf("%d%d",&y1,&y2); printf(" "); printf("请输入存储所有路径的文件名:"); scanf("%s",filename1); printf(" "); printf("请输入存储最短路径的文件名:"); scanf("%s",filename2); system("cls"); k=search(x1,x2,y1,y2,s1,s2,f1,filename1); if(k==1) Print(s2,filename2); printf("\n"); }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zygswo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值