P1135
#include <bits/stdc++.h>
using namespace std;
struct pos{
int step,lev;
};
int n,a,b;
int k[202],vis[202];
int bfs(){
pos cur,nex;
cur.lev=a,cur.step=0;
queue<pos> q;
q.push(cur);
vis[a]=1;
while(!q.empty()){
cur=q.front();
q.pop();
if(cur.lev==b) return cur.step;
nex.step=cur.step+1;
nex.lev=cur.lev+k[cur.lev];
if(nex.lev<=n&&vis[nex.lev]==0){
vis[nex.lev]=1;
q.push(nex);
}
nex.lev=cur.lev-k[cur.lev];
if(nex.lev>0&&vis[nex.lev]==0){
vis[nex.lev]=1;
q.push(nex);
}
}
return -1;
}
int main(){
cin>>n>>a>>b;
for(int i=1;i<=n;i++) scanf("%d",&k[i]);
cout<<bfs();
}
思路:bfs算法。先把起始状态(位置为起点,step为0)入队,然后不断访问队首元素,把下一步能到达的且未访问的楼层都入队,step加1,并将队首出队,直到访问到目标楼层或队列为空(搜索完了,无法到达)。
P1443
#include <bits/stdc++.h>
using namespace std;
struct pos{
int step;
int x,y;
};
int n,m,a,b;
int k[8][2]={{-1,2},{1,-2},{1,2},{-1,-2},{2,1},{-2,1},{2,-1},{-2,-1}};
int vis[401][401],rst[401][401];
void bfs(){
pos cur,nex;
cur.x=a,cur.y=b,cur.step=0;
queue<pos> q;
q.push(cur);
vis[a][b]=1,rst[a][b]=0;
while(!q.empty()){
cur=q.front();
q.pop();
nex.step=cur.step+1;
for(int i=0;i<8;i++){
nex.x=cur.x+k[i][0],nex.y=cur.y+k[i][1];
if(nex.x<=n&&nex.y<=m&&nex.x>0&&nex.y>0&&vis[nex.x][nex.y]==0){
vis[nex.x][nex.y]=1,rst[nex.x][nex.y]=nex.step;
q.push(nex);
}
}
}
}
int main(){
memset(rst,-1,sizeof(rst));
cin>>m>>n>>b>>a;
bfs();
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
printf("%-5d",rst[j][i]);
}
if(i<m) cout<<"\n";
}
}
思路:依然是bfs。用一个数组储存移动的方式。先把所有格子初始化为-1,每次访问到一个格子就记录下此时的step,直到队列为空。
P3958
#include <bits/stdc++.h>
using namespace std;
typedef struct{
double x,y,z;
}hole;
int pre[1001];
hole h[1001];
int root(int x){
return pre[x]=(pre[x]==x?x:root(pre[x]));
}
void merge(int x,int y){
x=root(x),y=root(y);
pre[x]=y;
}
double d(int a,int b){
return sqrt(pow(h[a].x-h[b].x,2)+pow(h[a].y-h[b].y,2)+pow(h[a].z-h[b].z,2));
}
void solve(int n,long hh,long r){
for(int i=0;i<n;i++) pre[i]=i;
for(int i=1;i<n;i++){
for(int j=0;j<i;j++){
if(root(i)!=root(j)&&d(i,j)<=2*r) merge(i,j);
}
}
for(int i=0;i<n;i++){
if(h[i].z<=r){
for(int j=0;j<n;j++){
if(h[j].z+r>=hh&&root(i)==root(j)){
printf("Yes\n");
return;
}
}
}
else if(h[i].z+r>=hh){
for(int j=0;j<n;j++){
if(h[j].z<=r&&root(i)==root(j)){
printf("Yes\n");
return;
}
}
}
}
printf("No\n");
}
int main(){
int T;
int n;
long hh,r;
cin>>T;
for(int i=0;i<T;i++){
cin>>n>>hh>>r;
for(int j=0;j<n;j++){
cin>>h[j].x>>h[j].y>>h[j].z;
}
solve(n,hh,r);
}
}
思路:并查集+路径压缩。把能联通的洞都合并到一棵树里,然后直接遍历查询是否有能联通上下表面的树。
P1162
#include <bits/stdc++.h>
using namespace std;
int n;
int a[32][32],vis[32][32];
int move[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
typedef struct{
int x,y,step;
}pos;
void bfs(int i,int j){
queue<pos> q;
pos cur={i,j,0};
q.push(cur);
pos nex;
while(!q.empty()){
cur=q.front();
q.pop();
nex.step=cur.step+1;
for(int i=0;i<4;i++){
nex.x=cur.x+move[i][0];
nex.y=cur.y+move[i][1];
if(nex.x>=0&&nex.x<=n+1&&nex.y&&nex.y<=n+1&&vis[nex.x][nex.y]==0&&a[nex.x][nex.y]==0){
vis[nex.x][nex.y]=1;
q.push(nex);
}
}
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&a[i][j]);;
for(int i=1;i<=n;i++){
if(a[i][1]==0){
bfs(i,1);
goto label;
}
else if(a[i][n]==0){
bfs(i,n);
goto label;
}
}
for(int j=1;j<=n;j++){
if(a[1][j]==0){
bfs(1,j);
goto label;
}
else if(a[n][j]==0){
bfs(n,j);
goto label;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(a[i][j]==0) cout<<2<<" ";
else cout<<1<<" ";
}
cout<<endl;
}
return 0;
label:
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(a[i][j]==0){
if(vis[i][j]==0) printf("2 ");
else printf("0 ");
}
else printf("1 ");
}
cout<<endl;
}
}
思路:逆向思维,被围住的0不好搜,搜索没有被围住的0。开一个大一圈的二维数组并且周围都为0,方便bfs。