一.入门级
P1747 好奇怪的游戏
P1747 好奇怪的游戏
题目描述
爱与愁大神坐在公交车上无聊,于是玩起了手机。一款奇怪的游戏进入了爱与愁大神的眼帘:***(游戏名被打上了马赛克)。这个游戏类似象棋,但是只有黑白马各一匹,在点x1,y1和x2,y2上。它们得从点x1,y1和x2,y2走到1,1。这个游戏与普通象棋不同的地方是:马可以走“日”,也可以像象走“田”。现在爱与愁大神想知道两匹马到1,1的最少步数,你能帮他解决这个问题么?
思路: 基础的入门题
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stdio.h>
#include<cmath>
#include<deque>
#include<queue>
#define debug cout<<"ok"<<endl
typedef long long ll;
const int maxn=1e3+1;
const int mod=1e9+7;
using namespace std;
struct node
{
int x,y,step;
node(int a=0,int b=0,int c=0)//结构体函数
{
x=a,y=b,step=c;
}
};
int dx[12]={1,1,2,2,2,2,-1,-1,-2,-2,-2,-2};//走法
int dy[12]={-2,2,-2,-1,1,2,-2,2,-1,1,-2,2};
int x1,x2,y_1,y2;
bool vis[maxn][maxn];//标记是否走过
queue<node>q;//队列实现bfs
void bfs(int a,int b)
{
q.push(node(a,b,0));//放
vis[a][b]=true;//标
while(!q.empty())
{
node nn=q.front();//取
q.pop();//扔
for(int i=0;i<12;i++)
{
int nx=nn.x+dx[i];//走
int ny=nn.y+dy[i];
if(nx>0&&ny>0&&!vis[nx][ny]&&nx<100&&ny<100)//判
{
q.push(node(nx,ny,nn.step+1));//放
vis[nx][ny]=true;//标
}
if(nx==1&&ny==1)//判
{
cout<<nn.step+1<<endl;
return;
}
}
}
}
int main()
{
cin>>x1>>y_1>>x2>>y2;
bfs(x1,y_1);
memset(vis,false,sizeof(vis));
while(!q.empty())q.pop();//清空
bfs(x2,y2);
return 0;
}
另一种思路: dfs+记忆化搜素
#include<bits/stdc++.h>
using namespace std;
int x,y,f[30][30];
//f[i][j]:从i,j走到1,1所需的最小步数
int dx[13]={0,-2,-2,+2,+2,-1,-1,+1,+1,-2,-2,+2,+2};
int dy[13]={0,-1,+1,-1,+1,-2,+2,-2,+2,-2,+2,-2,+2};
//马字8个方向,田字4个方向
void dfs(int x,int y,int step) //记忆化搜索,走到x,y花了step步
{
f[x][y]=step; //更新最小步数
for (int i=1;i<=12;i++) //12个方向走一遍
{
int xx=x+dx[i];
int yy=y+dy[i];
if (xx>=1&&xx<=20&&yy>=1&&yy<=20&&(f[xx][yy]==0||f[xx][yy]>step+1)) dfs(xx,yy,step+1);
//如果没超出边界并且xx,yy可以被更新,就继续走
}
}
int main()
{
for (int i=1;i<=2;i++)
{
scanf("%d%d",&x,&y);
memset(f,0,sizeof(f));
dfs(x,y,0); //走到x,y需要0步
printf("%d\n",f[1][1]); //最后输出
}
return 0;
}
赞,dfs天下第一,能用dfs就不用bfs
链接:https://ac.nowcoder.com/acm/contest/322/B
来源:牛客网
TRDD got lost again
TRDD got lost again
题目描述
X城市是一个交通十分不便利的城市,城市可以看成一个n * m大小的矩阵, 现在TRDD手里有该城市的地图:一个2*n+1行, 2 *m+1列大小的地图。现在TRDD所在的格子用S表示,机场所在的格子用T表示。 其他格子用空格表示,地图上左右相邻的两个格子如果不能通行用"|“表示, 上下相邻的两个点如果不能通行用”-“表示,”+“表示格子的四个角。 题目保证城市X最外圈无法通行(具体请看样例输入)。 为了能尽快赶到机场,TRDD想请你帮忙计算出他到达机场最少需要走过多少个格子(包括起点S和终点T)。 如果无法到达机场T,则输出"TRDD Got lost…TAT”(不包括双引号)。
输入描述:
第一行读入两个数n, m(1 <= n, m <= 3000)表示X城市的大小。之后有2 * n + 1行, 每行有2 * m + 1个字符, 用来表示TRDD手里的地图题目保证S和T都有且仅有一个。
输出描述:
如果TRDD能到达机场, 则输出TRDD最少需要经过几个格子否则输出"TRDD Got lost…TAT"(不包括双引号)
输入:
4 3
+-+-+-+
|S| | |
+ +-+-+
| | | |
+ +-+-+
| |T |
+ +-+ +
| |
+-+-+-+
输出:8
由于数据量过大,建议不要使用scanf("%c")读入,否则可能会TLE。
思路:此题细节颇多,注意c++11可以用gets()
,而c++14却不能用(gets
有安全隐患故删除)
#include<bits/stdc++.h>
#define debug cout<<"ok"<<endl
typedef long long ll;
const int maxn=6005;
const int mod=1e9+7;
using namespace std;
int n,m,nx,ny,steps,ans,tx,ty,sx,sy;
inline int read()
{
int x=0,f=0;
char ch=getchar();
while(ch>'9'||ch<'0'){f|=(ch=='-');ch=getchar();}
while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return f?-x:x;
}
int dx[]={1,-1,0,0};
int dy[]={0,0,1,-1};
bool vis[maxn][maxn];
char mp[maxn][maxn];
struct node
{
int x,y,step;
node(int a=0,int b=0,int c=0)
{
x=a,y=b,step=c;
}
};
queue<node>q;
void bfs(int x,int y)
{
vis[x][y]=true;
q.push(node(x,y,1));
while(!q.empty())
{
nx=q.front().x;
ny=q.front().y;javascript:void(0);
steps=q.front().step;
q.pop();
for(int i=0;i<4;i++)
{
int xx=nx+dx[i];
int yy=ny+dy[i];
if(xx>0&&yy>0&&xx<=n&&yy<=m&&!vis[xx][yy]&&(mp[xx][yy]=='T'||mp[xx][yy]==' '))
{
q.push(node(xx,yy,steps+1));
javascript:void(0); vis[xx][yy]=true;
}
if(mp[xx][yy]=='T')
{
cout<<(steps+2)/2<<endl;
return ;
}
}
}
printf("TRDD Got lost...TAT\n");
}
int main()
{
memset(vis,false,sizeof(vis));
//n=read(),m=read();//快读就不需要加getchr()快读万岁!!;
cin>>n>>m;
getchar();//注意必须要有这个getcgar()!!;
m=2*m+1;
n=2*n+1;
int flag=0;
for(int i=1;i<=n;i++)
{
gets(mp[i]);
if(!flag)
for(int j=1;j<=m;j++)
if(mp[i][j]=='S'){sx=i,sy=j;flag=1;}
}
bfs(sx,sy);
return 0;
}
二.进阶
final的BFS Abbott’s Revenge
注:如果您通过本文,有(qi)用(guai)的知识增加了,请您点个赞再离开,如果不嫌弃的话,点个关注再走吧 ! 当然,也非常欢迎您能在讨论区指出此文的不足处,作者会及时对文章加以修正 !如果有任何问题,欢迎评论,非常乐意为您解答!( •̀ ω •́ )✧