每日一题——魔鬼之城

**每日一题——魔鬼之城

题目传送门----魔鬼之城

—————————————我是分割线———————————————
题目解读
标准BFS或DFS,我是用BFS打的

可是题干中的这句话

因为这样他第二次跳跃的方向将和第一次相同,而这是不允许的>

导致我们在DFS或BFS时需要四个参

struct made{
	int x;//横坐标
	int y;//竖坐标
	int t;//时间
	int f;//上一次是从哪里过来的
};
queue<made> q;

可是与其他标准BFS不同的还有它可以向八个方向:上下左右,还有四条斜边。并且再每一个格子行走的距离必须是当前格子的值。如果剩余格子长度则不够无法行走。

—————————————我是分割线———————————————

思路诠述
使用一个三维数组

bool f[110][110][9]={};

第一维和第二维表示当前所在的点,第三维表示在八个方向走过没有;
如果走过则不能再走;
注意!!题目说这次走的方向不能和上次一样
————————————我是分割线————————————————
代码展示

在这里插入#include<bits/stdc++.h>
using namespace std;
int a[110][110];
struct made{
	int x;//横坐标
	int y;//竖坐标
	int t;//时间
	int f;//上一次是从哪里过来的
};
bool f[110][110][9]={};
queue<made> q;//made 队列
int main()
{
	int n,m;
	scanf("%d%d",&m,&n);//**注意题目是先读列再读行**
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			scanf("%d",&a[i][j]);
	q.push((made){1,1,0,0});//从第一行第一个各自开始,走了0步,上一次没有方向
	while(!q.empty()){
		int xx=q.front().x;
		int yy=q.front().y;
		int tt=q.front().t;
		int ff=q.front().f;
//		printf("ff== %d\n",ff);
		q.pop();
		if(xx==n&&yy==m){
			printf("%d",tt);
			return 0;
		}
		else{//八个方向搜索
//			printf("xx== %d,yy== %d,tt== %d\n",xx,yy,tt);
			if(xx-a[xx][yy]>=1&&xx-a[xx][yy]<=n&&yy>=1&&yy<=n&&f[xx][yy][1]==0&&ff!=1){
				q.push((made){xx-a[xx][yy],yy,tt+1,1});
				f[xx][yy][1]=1;//不能再走
			}
			if(yy-a[xx][yy]>=1&&yy-a[xx][yy]<=m&&xx>=1&&xx<=n&&f[xx][yy][7]==0&&ff!=7){
				q.push((made){xx,yy-a[xx][yy],tt+1,7});
				f[xx][yy][7]=1;//以下相同代码同上
			}
			if(xx+a[xx][yy]<=n&&xx+a[xx][yy]>=1&&yy<=m&&yy>=1&&f[xx][yy][5]==0&&ff!=5){
				q.push((made){xx+a[xx][yy],yy,tt+1,5});
				f[xx][yy][5]=1;
			}
			if(yy+a[xx][yy]<=m&&yy+a[xx][yy]>=1&&xx>=1&&xx<=n&&f[xx][yy][3]==0&&ff!=3){
				q.push((made){xx,yy+a[xx][yy],tt+1,3});
				f[xx][yy][3]=1;
			}
			if(xx+a[xx][yy]<=n&&xx+a[xx][yy]>=1&&yy+a[xx][yy]>=1&&yy+a[xx][yy]<=m&&f[xx][yy][4]==0&&ff!=4){
				q.push((made){xx+a[xx][yy],yy+a[xx][yy],tt+1,4});
				f[xx][yy][4]=1;
			}
			if(xx+a[xx][yy]<=n&&xx+a[xx][yy]>=1&&yy-a[xx][yy]>=1&&yy-a[xx][yy]<=m&&f[xx][yy][6]==0&&ff!=6){
				q.push((made){xx+a[xx][yy],yy-a[xx][yy],tt+1,6});
				f[xx][yy][6]=1;
			}
			if(xx-a[xx][yy]>=1&&xx-a[xx][yy]<=n&&yy-a[xx][yy]>=1&&yy-a[xx][yy]>=1&&f[xx][yy][2]==0&&ff!=2){
				q.push((made){xx-a[xx][yy],yy-a[xx][yy],tt+1,2});
				f[xx][yy][2]=1;
			}
			if(xx-a[xx][yy]>=1&&xx-a[xx][yy]<=n&&yy+a[xx][yy]<=m&&yy+a[xx][yy]>=1&&f[xx][yy][8]==0&&ff!=8){
				q.push((made){xx-a[xx][yy],yy+a[xx][yy],tt+1,8});
				f[xx][yy][8]=1;
			}
		}
	}
	printf("NEVER");
	return 0;
}//完美结尾

——————————————我是分割线——————————————
反思
没有使用方向数组导致代码冗长;
读题不够完善;

上一篇:JavaScript中对大量数据的多重过滤


下一篇:重新精读《Java 编程思想》系列之组合与继承