一.P1135 奇怪的电梯
思路:
我们根据stl的队列的使用,我们可以利用它来进行二叉树的遍历,这就是广度搜索(BFS)的基础。而根据题目,每一次按按钮都有两种(当然,排除超出1-n范围的种类),故可以广度搜索每一种可能,直到到达终点。注意有排除前面已经走过的点,这样不仅可以加速,还可以保证求出的按键次数为最小的次数。
具体 BFS 的代码说明见注释。
代码如下:
//广度优先搜索 BFS
#include<bits/stdc++.h>
using namespace std;
struct pos //结构体存储状态
{
int lev,stp;
} ;
queue<pos> qu; //建立队列保存状态。
int a[202];
int vis[202]; //vis 保存是否已经搜索过了。
int n,sta,end1; //sta 表示起点; end 表示终点。
void bfs ()
{
pos now,nex;
now.lev=sta;
now.stp=0;
// queue<pos> qu; //建立队列保存状态。
qu.push(now);
vis[sta]=1;
while (!qu.empty()) //开始遍历。
{
now=qu.front();
qu.pop();
if (now.lev==end1)
{
cout<<now.stp;
return ;
}
// 开始搜索;
// 向上
nex.lev=now.lev+a[now.lev];
nex.stp=now.stp+1;
if (nex.lev <= n && vis[nex.lev]==0)
{
vis[nex.lev]=1;
qu.push(nex);
}
//向下
nex.lev=now.lev-a[now.lev];
nex.stp=now.stp+1;
if (nex.lev >= 0 && vis[nex.lev]==0)
{
vis[nex.lev]=1;
qu.push(nex);
}
}
cout<<"-1";
return ;
}
int main()
{
cin>>n>>sta>>end1;
for (int i=1;i<=n;i++)
{
cin>>a[i];
vis[i]=0;
}
bfs();
return 0;
}
二.P1443 马的遍历
思路:
本题还是bfs的思路,与上一题唯一不同的是马有8种走法,故每一次搜索有8种可能(即每一个父节点下有8个子节点,有8种路径)。所以我们可以用数组存储并加上for循环进行遍历所有路径。
本题的重难点:①每一点都bfs的时候,注意vis的位置放置正确,保证重置为0 。②前往不要每一个点bfs一次,会TLE的,可以只bfs一次用vis保存每一点的次数。
代码如下:
#include<bits/stdc++.h>
using namespace std;
struct pos
{
int x,y,step;
};
int dx[8]={-2,-2,2,2,1,-1,1,-1};
int dy[8]={-1,1,-1,1,2,-2,-2,2};
int n,m,sx,sy;
int vis[405][405];
void bfs (int ex,int ey)
{
queue <pos> qu;
pos now,nex;
now.x=sx;
now.y=sy;
now.step=0;
qu.push(now);
vis[sx][sy]=now.step;
while (!qu.empty()) //开始遍历。
{
now=qu.front();
qu.pop();
/*if (now.x==ex && now.y==ey)
{
cout<<now.step;
return ;
}*/
// 开始搜索;
for (int k=0;k<8;k++)
{
nex.x=now.x+dx[k];
nex.y=now.y+dy[k];
nex.step=now.step+1;
if (nex.x <= n && nex.x >=1 && nex.y <= m && nex.y >=1 && vis[nex.x][nex.y]==-1)
{
vis[nex.x][nex.y]=nex.step;
qu.push(nex);
}
}
}
//cout<<-1;
return ;
}
int main()
{
cin>>n>>m>>sx>>sy;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
vis[i][j]=-1;
bfs(1,1);
for (int i=1;i<=n;i++)
{
for (int j=1;j<=m;j++)
{
/*if (i==sx && j==sy) cout<<0;
else if (vis[i][j]) cout<<vis[i][j];
else bfs(i,j);*/
cout<<vis[i][j];
cout<<" ";
}
cout<<"\n";
}
return 0;
}
三.P3958 [NOIP2017 提高组] 奶酪
思路:
本题题目复杂,但在本蒟蒻看来并不太难,与上面bfs的思路相同。
注意:这题有个新手容易入的坑,就是cout<<"No"<<endl;将endl去掉,这是在测试的时候看似没问题(如下),但根据oj的测评方式会WA的!!!
3
2 4 1
0 0 1
0 0 3
YES 2 5 1
0 0 1
0 0 4
NO 2 5 2
0 0 2
2 0 4
YES
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1005;
ll r,n,h;
ll x[maxn],y[maxn],z[maxn];
struct pos
{
ll x,y,z,height;
};
void bfs()
{
cin>>n>>h>>r;
for (int i=0;i<n;i++) cin>>x[i]>>y[i]>>z[i];
for (int i=0;i<n;i++)
if (z[i]<=r)
{
bool vis[maxn];
for (int k=0;k<n;k++) vis[k]=0;
pos now,next;
now.x=x[i]; now.y=y[i]; now.z=z[i],now.height=z[i]+r;
queue <pos> q;
q.push(now);
vis[i]=1;
while (!q.empty())
{
now=q.front();
q.pop();
if (now.height >= h)
{
cout<<"Yes"<<endl;
return ;
}
for (int j=0;j<n;j++)
if (j!=i and vis[j]==0)
{
double dis=pow(now.x-x[j],2)+pow(now.y-y[j],2)+pow(now.z-z[j],2);
//if (!f(now.x,now.y,now.z,x[j],y[j],z[j])) continue;
if (dis <= 4*r*r)
{
next.x=x[j]; next.y=y[j]; next.z=z[j];
next.height= z[j]+r;
q.push(next);
vis[j]=1;
}
}
}
}
cout<<"No"<<endl;
return ;
}
int main()
{
int www;
cin>>www;
while(www--)
{
bfs();
}
return 0;
}
四.P1162 填涂颜色
思路:
bfs + 反射(反过来,搜索外层)(染色)。 将非1的全改为2,从外面搜索,见2改为0 。
本题要注意:注意dfs中的if语句,我在最外面多加了一圈0,这样子就相当于把外圈所有的0都连通起来,四面八方所有的0都可以被搜到,只会留下中间的1。
代码如下:
#include<bits/stdc++.h>
using namespace std;
struct pos
{
int x,y;
};
const int xx[4]={1,-1,0,0};
const int yy[4]={0,0,1,-1};
int n,a[35][35],b[35][35];
int main()
{
for(int i=0;i<35;i++)
for(int j=0;j<35;j++)
a[i][j]=2;
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int tmd;
cin>>tmd;
if(tmd==1)a[i][j]=1;
}
}
//bfs:
queue<pos> q;
pos now,next;
now.x=0;
now.y=0;
q.push(now);
while (q.size())
{
now=q.front();
q.pop();
for (int i=0;i<4;i++)
{
next.x=now.x+xx[i];
next.y=now.y+yy[i];
if (next.x>=0 and next.x<=n+1 and next.y>=0 and next.y<=n+1 and a[next.x][next.y]==2)
{
a[next.x][next.y]=0;
q.push(next);
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cout<<a[i][j]<<" ";
}
if(i!=n)cout<<endl;
}
return 0;