1. P1135 奇怪的电梯
好的,BFS(一顿暴搜外加数组优化就ok)。
(1)构建状态:这里用的结构体,分别记录当前楼层和下一楼层,包括它们的层级数 和到这层的min步数。
(2)构造二叉树:从当前楼层向上向下移动,如果能到下一层(不超过边界 && 之前没到过这一 层),将下一层加入队列。
(3)判断输出:如果当前楼层为目标楼层,输出步数;
如果到不了目标楼层,即队列为空,二叉树构造完成也没出现该楼层,输出-1。
(4)数组优化:定义一个数组vis[ ]初始值均为0,如果到达第i层,将vis[ i ] = 1,表示已经到过。
#include <bits/stdc++.h>
using namespace std;
int n,a,b;
int k[210],vis[210];
//int ans = -1;
struct pos
{
int level;//楼层
int step;//步数
};
void bfs()
{
pos cur,next;//定义当前楼层和下一层
cur.level = a;//初始化
cur.step = 0;
queue<pos> qu;
qu.push(cur);
vis[a] = 1;
while(!qu.empty()){
cur = qu.front();
qu.pop();
if(cur.level == b){
cout<<cur.step<<endl;
return ;
}
//向上
next.level = cur.level + k[cur.level];
next.step = cur.step+1;
if(next.level <= n)
if(vis[next.level] == 0){
vis[next.level] = 1;
qu.push(next);
}
//向下
next.level = cur.level - k[cur.level];
next.step = cur.step+1;
if(next.level >= 1)
if(vis[next.level] == 0){
vis[next.level] = 1;
qu.push(next);
}
}
cout<<"-1";
return ;
}
int main()
{
cin>>n>>a>>b;
for(int i=1;i<=n;i++){
cin>>k[i];
vis[i] = 0;
}
bfs();
return 0;
}
2.P1443 马的遍历
典例BFS。
用STL中的队列queue辅助构建马移动路线(树):马走日,如果从点(i , j)出发有八个方向可以走即点(i+d[x],j+d[y]),如果移动后没出界 && 之前没来过(i+d[x],j+d[y]),则把(i+d[x],j+d[y])加入队列,标记vis(i+d[x],j+d[y])=1表示来过,步数+1,并从队列中弹出点(i , j)。
#include <bits/stdc++.h>
using namespace std;
int n,m,x,y;
int vis[405][405],ans[405][405];
queue<int> qx,qy;//分别记录横纵坐标的变化
int dx[8]={-2,-2,2,2,1,-1,1,-1};
int dy[8]={-1,1,-1,1,2,-2,-2,2};//8个方向
void bfs()
{
memset(ans,-1,sizeof(ans));
qx.push(x);
qy.push(y);
ans[x][y] = 0;
vis[x][y] = 1;
while(!qx.empty()){
for(int i=0;i<8;i++){
int tempx = qx.front()+dx[i];
int tempy = qy.front()+dy[i];
if(tempx>0 && tempx<=n && tempy>0 && tempy<=m && vis[tempx][tempy]==0){
vis[tempx][tempy] = 1;
ans[tempx][tempy] = ans[qx.front()][qy.front()]+1;
qx.push(tempx);
qy.push(tempy);
}
}
qx.pop();
qy.pop();
}
}
int main()
{
cin>>n>>m>>x>>y;
bfs();
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
printf("%-5d",ans[i][j]);//控制
}
printf("\n");
}
return 0;
}
3.P3958 [NOIP2017 提高组] 奶酪
原题指路:P3958 [NOIP2017 提高组] 奶酪 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P3958
先依据洞的高度进行结构体排序,在从前往后遍历洞的数组,如果能和前面的洞相连(两球心的距离大于等于2r)则加入tree[ ],如果遍历结束最后一个洞能到达奶酪上表面,输出"Yes",反之,输出"No"。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
struct pos
{
ll x;
ll y;
ll z;
};
bool cmp(pos a,pos b)
{
if(a.z != b.z) return a.z<b.z;
if(a.x != b.x) return a.x<b.x;
return a.y<b.y;
}
pos tree[1010],g[1010];
ll dist(ll x1,ll y1,ll z1,ll x2,ll y2,ll z2)
{
return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2);
}
int main()
{
ll t,n,h,r,s;
int flag=0;
cin>>t;
for(int c=1;c<=t;c++)
{
scanf("%lld%lld%lld",&n,&h,&r);
s=0;
flag=0;
memset(tree,0,sizeof(tree));//以上是初始化
for(int i=1;i<=n;i++)
scanf("%lld%lld%lld",&g[i].x,&g[i].y,&g[i].z);
sort(g+1,g+1+n,cmp);//排序
for(int i=1;i<=n;i++)
{
flag=0;
if(g[i].z-r<=0)//如果与下底面相连就直接存入数组
{
s++;
tree[s].x=g[i].x;
tree[s].y=g[i].y;
tree[s].z=g[i].z;
}
for(int j=1;j<=s;j++)
if(dist(g[i].x,g[i].y,g[i].z,tree[j].x,tree[j].y,tree[j].z)<=4*r*r)//判断是否相切或相交
{
s++;
tree[s].x=g[i].x;
tree[s].y=g[i].y;
tree[s].z=g[i].z;
break;
}
if(tree[s].z+r>=h)//判断是否与上顶面相连
{
flag=1;
break;
}
}
if(flag)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
4.P1162 填涂颜色
原题指路:P1162 填涂颜色 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P1162
本题有很多种解决方法,蒟蒻这里只提其中一种。
核心思想:1.把所有的2赋成0
2. 把边界处的2改回0
3.把与边界处与0相邻的2改回0
#include <bits/stdc++.h>
using namespace std;
int n;
int a[35][35];
int xx[] = {0,0,-1,1};
int yy[] = {-1,1,0,0};
void bfs()
{
//把边界处的2改回0
for(int i=0;i<n;i++){
if(a[0][i]==2) a[0][i]=0;
if(a[i][0]==2) a[i][0]=0;
if(a[n][i]==2) a[n][i]=0;
if(a[i][n]==2) a[i][n]=0;
}
//把与边界处与0相邻的2改回0
for(int k=1;k<=100;k++){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(a[i][j] != 1){
if(a[i][j-1]==0 || a[i][j+1]==0 || a[i-1][j]==0 || a[i+1][j]==0)
a[i][j] = 0;
}
}
}
}
return ;
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++){
cin>>a[i][j];
if(a[i][j] == 0)
a[i][j] = 2;//把所有的0赋成2
}
bfs();
for(int i=0;i<n;i++)
for(int j=0;j<n;j++){
cout<<a[i][j];
if(j!=n-1) cout<<' ';
else cout<<'\n';
}
return 0;
}