基础搜索入门BFS
BFS全称宽度优先搜索算法(又称广度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。通俗一点的说就像你向一块平静的湖面丢一块石头,会荡出一层一层的水波,而且水波是由近及远的,通常BFS搜索需要搭配队列或者优先队列来辅助搜索过程。
HDU1253
广度优先搜索第一道题 bfs + queue
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <queue>
using namespace std;
struct Node{
int x,y,z,step;
};
queue<Node>q;
int map[50][50][50];
int visited[50][50][50];
int dx[6] = { 1,0,-1,0,0,0 };
int dy[6] = { 0,1,0,-1,0,0 };
int dz[6] = { 0,0,0,0,1,-1 };
int BFS(int a,int b,int c,int time)
{
while(q.empty()==false){
Node p = q.front();
q.pop();
if(time<p.step){
break;
}
for(int i = 0;i < 6;i++){
int nx = p.x+dx[i];
int ny = p.y+dy[i];
int nz = p.z+dz[i];
if(nx<0||nx>=a||ny<0||ny>=b||nz<0||nz>=c||
visited[nx][ny][nz]==1||map[nx][ny][nz]==1){
continue;
}
Node ptr;
ptr.x = nx;ptr.y = ny;ptr.z = nz;ptr.step = p.step+1;
q.push(ptr);
visited[ptr.x][ptr.y][ptr.z] = 1;
if(nx == a-1 && ny == b-1 && nz == c-1){
return ptr.step;
}
}
}
return 2000;
}
int main()
{
int a,b,c,t,time;
scanf("%d",&t);
while(t--){
scanf("%d%d%d%d",&a,&b,&c,&time);
for (int i = 0; i < a; i++){
for (int j = 0; j < b; j++){
for(int k = 0;k < c;k++){
scanf("%d",&map[i][j][k]);
visited[i][j][k] = 0;
}
}
}
while(!q.empty()){
q.pop();
}
Node start;
start.x = 0;start.y = 0;start.z = 0;start.step = 0;
q.push(start);
visited[0][0][0] = 1;
int ans = BFS(a,b,c,time);
if(ans>time){
printf("-1\n");
}
else{
printf("%d\n",ans);
}
}
return 0;
}
HDU1242
搜索第二题,bfs + queue,但是经过后来的学习发现这道题这么做是错误的,应该用优先队列.
目标只有一个,但是救援人员可以有多个,测试数据有点水没出到位详情请右转正解链接
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
using namespace std;
int m,n,start_x,start_y;
struct Node{
int x,y,step;
bool operator <(const Node &s)const{
return s.step < step;
}
};
char map[201][201];
int visited[201][201];
int dx[4] = {1,-1,0,0};
int dy[4] = {0,0,1,-1};
priority_queue<Node>q;
int BFS()
{
while(!q.empty()){
Node p = q.top();
q.pop();
for(int i = 0;i < 4;i++){
int nx = p.x+dx[i];
int ny = p.y+dy[i];
int step = p.step+1;
if(nx<0||nx>=m||ny<0||ny>=n||map[nx][ny]=='#'||visited[nx][ny]==1){
continue;
}
Node ptr;
ptr.x = nx;ptr.y = ny;ptr.step = step;
if(map[ptr.x][ptr.y]=='x'){
// cout<<"jinlai"<<endl;
ptr.step += 1;
}
if(map[nx][ny]=='r'){
return ptr.step;
}
q.push(ptr);
visited[ptr.x][ptr.y] = 1;
}
}
return -1;
}
int main()
{
while(cin>>m>>n){
for(int i = 0;i < m;i++){
for(int j = 0;j < n;j++){
cin>>map[i][j];
visited[i][j] = 0;
if(map[i][j] == 'a'){
start_x = i,start_y = j;
}
}
}
while(!q.empty()){
q.pop();
}
Node start;
start.x = start_x;start.y = start_y;start.step = 0;
visited[start.x][start.y] = 1;
q.push(start);
int ans = BFS();
if(ans==-1){
cout<<"Poor ANGEL has to stay in the prison all his life."<<endl;
}
else{
cout<<ans<<endl;
}
}
return 0;
}
HDU1072
搜索第三题,这题需要一定的模拟技巧,注意好炸弹时间。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
using namespace std;
int m,n,start_x,start_y;
struct Node{
int x,step;
int y,time;
};
int map[10][10];
int visited[10][10];
int dx[4] = {1,-1,0,0};
int dy[4] = {0,0,1,-1};
queue<Node>q;
int BFS()
{
while(!q.empty()){
Node p = q.front();
q.pop();
if(p.time==0){
continue;
}
if(map[p.x][p.y]==3){
return p.step;
}
for(int i = 0;i < 4;i++){
int nx = p.x+dx[i];
int ny = p.y+dy[i];
if(nx<0||nx>=n||ny<0||ny>=m||map[nx][ny]==0){
continue;
}
int step = p.step+1;
int time = p.time-1;
Node ptr;
ptr.x = nx;ptr.y = ny;ptr.step = step;ptr.time = time;
if(map[ptr.x][ptr.y]==4&&ptr.time){
map[ptr.x][ptr.y] = 1;
ptr.time = 6;
}
q.push(ptr);
}
}
return -1;
}
int main()
{
int t;
cin>>t;
while(t--){
cin>>n>>m;
for(int i = 0;i < n;i++){
for(int j = 0;j < m;j++){
cin>>map[i][j];
if(map[i][j]==2){
start_x = i;
start_y = j;
}
visited[i][j] = 0;
}
}
while(!q.empty()){
q.pop();
}
Node start;
start.x = start_x;start.y = start_y;start.step = 0;start.time = 6;
q.push(start);
int ans = BFS();
cout<<ans<<endl;
}
return 0;
}
POJ3984
搜索第四题,BFS路径打印问题,路径打印方法不止一种,这是我学过最好的路径打印了。网上大部分都借用了stack容器或者递归回溯打印
#include <iostream>
#include <string.h>
#include <string>
#include <vector>
#include <queue>
#include <stdio.h>
#include <algorithm>
#define INF 0x3f3f3f3f
#define MAXN 100010
using namespace std;
int mp[10][10],vis[10][10];
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
struct Node{
int x,y;
int stepx[30],stepy[30],cnt;
}a;
queue<Node>q;
void BFS()
{
while(!q.empty()){
Node p = q.front(),ptr;
q.pop();
if(p.x==4&&p.y==4){
printf("(0, 0)\n"); //起点
for(int i=0;i<p.cnt;i++)
printf("(%d, %d)\n",p.stepx[i],p.stepy[i]);
return ;
}
ptr = p; //少了这句话就会错,因为这句话执行了赋值操作。
for(int i=0;i<4;++i){
ptr.x=p.x+dx[i];
ptr.y=p.y+dy[i];
if(ptr.x>=0&&ptr.x<=4&&ptr.y>=0&&ptr.y<=4&&vis[ptr.x][ptr.y]==0&&mp[ptr.x][ptr.y]==0){
vis[ptr.x][ptr.y]=1;
ptr.stepx[ptr.cnt]=ptr.x;
ptr.stepy[ptr.cnt++]=ptr.y;
q.push(ptr);
}
}
}
}
int main()
{
for(int i = 0;i<5;++i){
for(int j = 0;j<5;++j){
cin>>mp[i][j];
vis[i][j] = 0;
}
}
while(!q.empty()){
q.pop();
}
Node start;
start.x = 0;start.y = 0;start.cnt = 0;
q.push(start);
BFS();
return 0;
}
HDU1026
搜索第五题 bfs + priority_queue + 路径打印。
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <queue>
#include <cmath>
using namespace std;
struct Node{
int x,y,s,cnt;
int stepx[1015],stepy[1105];
bool operator< (const Node &a)const{
if(a.s == s){
return a.cnt < cnt;
}
else{
return a.s < s;
}
}
};
char map[1105][1015];
bool visited[1105][1105];
int n,m;
int dx[] = {1,0,-1,0};
int dy[] = {0,1,0,-1};
int BFS()
{
priority_queue<Node>q;
while(!q.empty()){
q.pop();
}
Node t;t.x = 0;t.y = 0;t.s = 0;t.cnt = 0;
t.stepx[0] = 0;t.stepy[0] = 0;
visited[t.x][t.y] = true;
q.push(t);
while(!q.empty()){
Node p = q.top();
q.pop();
if(p.x == n-1 && p.y == m-1){
printf("It takes %d seconds to reach the target position, let me show you the way.\n",p.s);
int sum = 0;
for(int i = 1;i <= p.cnt;i++){
printf("%ds:(%d,%d)->(%d,%d)\n",sum+i,p.stepx[i-1],p.stepy[i-1],p.stepx[i],p.stepy[i]);
if(map[p.stepx[i]][p.stepy[i]] >= '1' && map[p.stepx[i]][p.stepy[i]] <= '9'){
int k = map[p.stepx[i]][p.stepy[i]] - '0';
for(int j = 0;j < k;j++){
printf("%ds:FIGHT AT (%d,%d)\n",sum+i+1+j,p.stepx[i],p.stepy[i]);
}
sum += k;
}
}
return 1;
}
t = p;
for(int i = 0;i < 4;i++){
t.x = p.x + dx[i];
t.y = p.y + dy[i];
if(t.x < 0 || t.x >= n || t.y < 0 || t.y >= m || visited[t.x][t.y] == true || map[t.x][t.y] == 'X'){
continue;
}
t.cnt = p.cnt + 1;
t.stepx[t.cnt] = t.x;
t.stepy[t.cnt] = t.y;
t.s = p.s + 1;
if(map[t.x][t.y] >= '1' && map[t.x][t.y] <= '9'){
t.s = t.s + map[t.x][t.y] - '0';
}
visited[t.x][t.y] = true;
q.push(t);
}
}
return 0;
}
int main()
{
while(~scanf("%d%d",&n,&m)){
for(int i = 0;i < n;i++){
scanf("%s",map[i]);
}
// m = strlen(map[0]);
memset(visited,false,sizeof(visited));
int ans = BFS();
if(ans == 0){
printf("God please help our poor hero.\n");
}
printf("FINISH\n");
}
return 0;
}
HDU1728
搜索第六题 bfs + queue 拐弯问题,解决方法就是一直往一个方向走,走完拐弯数就 + 1。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn = 110;
struct Node{
int x,y,k;
};
queue<Node>q;
int m,n,sx,sy,ex,ey,k;
int visited[maxn][maxn];
char map[maxn][maxn];
int dx[] = {1,-1,0,0};
int dy[] = {0,0,1,-1};
void new_set()
{
while(!q.empty()){
q.pop();
}
memset(visited,0,sizeof(visited));
}
bool check(int x,int y)
{
if(x >= 1 && x <= m && y >= 1 && y <= n && map[x][y] != '*'){
return true;
}
else{
return false;
}
}
void bfs()
{
Node s;
s.x = sx;s.y = sy;s.k = -1;
q.push(s);
visited[sx][sy] = 1;
int flag = 0;
while(!q.empty()){
Node p = q.front();
q.pop();
if(p.x == ex && p.y == ey && p.k <= k){
flag = 1;
break;
}
int sk = p.k + 1;
for(int i = 0;i < 4;i++){
int nx = p.x + dx[i];
int ny = p.y + dy[i];
while(check(nx,ny)){
if(visited[nx][ny] == 0){
Node ptr;
ptr.x = nx;
ptr.y = ny;
ptr.k = sk;
visited[nx][ny] = 1;
q.push(ptr);
}
nx += dx[i];
ny += dy[i];
}
}
}
if(flag == 1){
cout<<"yes"<<endl;
}
else{
cout<<"no"<<endl;
}
}
int main()
{
int t;
cin>>t;
while(t--){
cin>>m>>n;
for(int i = 1;i <= m;i++){
for(int j = 1;j <= n;j++){
cin>>map[i][j];
}
}
cin>>k>>sy>>sx>>ey>>ex;
new_set();
bfs();
}
return 0;
}
HDU1241
搜索第七题求联通的个数,bfs + queue。联通的就一次性全部标记好,算跑了几次bfs就知道有几块油田
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn = 105;
struct Node{
int x,y;
};
queue<Node>q;
int m,n;
int dx[] = {1,-1,0,0,1,-1,1,-1};
int dy[] = {0,0,1,-1,1,1,-1,-1};
char map[maxn][maxn];
int visited[maxn][maxn];
int check(int x,int y)
{
if(map[x][y] == '*' || visited[x][y] == 1 || x <= 0 || x > m || y <= 0 || y > n){
return false;
}
else{
return true;
}
}
void bfs(int x,int y)
{
queue<Node>q;
Node p,ptr;
p.x = x;p.y = y;
q.push(p);
while(!q.empty()){
p = q.front();
q.pop();
for(int i = 0;i < 8;i++){
ptr.x = p.x + dx[i];
ptr.y = p.y + dy[i];
if(check(ptr.x,ptr.y) == true){
visited[ptr.x][ptr.y] = 1;
q.push(ptr);
}
}
}
}
int main()
{
while(cin>>m>>n && m&&n){
for(int i = 1;i <= m;i++){
for(int j = 1;j <= n;j++){
cin>>map[i][j];
}
}
memset(visited,0,sizeof(visited));
int ans = 0;
for(int i = 1;i <= m;i++){
for(int j = 1;j <= n;j++){
if(visited[i][j] == 0 && map[i][j] == '@'){
bfs(i,j);
ans++;
}
}
}
cout<<ans<<endl;
}
return 0;
}
HDU1495
搜索第八题之倒水问题,想好转移情况和状态。bfs + queue
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <cmath>
using namespace std;
struct node{
int s,x,y;
int t;
};
const int maxn = 1e6;
bool visited[maxn];
queue<node>q;
void bfs(int s,int n,int m)
{
while(!q.empty()){
node ptr = q.front(),p;
q.pop();
if((ptr.s == ptr.x && ptr.s + ptr.x == s) ||
(ptr.s == ptr.y && ptr.s + ptr.y == s)){
printf("%d\n",ptr.t);
return ;
}
for(int i = 0;i < 6;i++){ //s,x,y两两互相倒存在6种情况
if(i == 0){ //s给x倒
if(ptr.x < n && ptr.s > 0){
if(ptr.s <= n - ptr.x){ //s中的可乐不够或者刚好够倒满x
p.s = 0;
p.x = ptr.s + ptr.x;
p.y = ptr.y;
}
else{ //s中的可乐能够倒满x
p.x = n;
p.s = ptr.s - (n - ptr.x);
p.y = ptr.y;
}
int t = p.s*10000 + p.x*100 + p.y;
if(visited[t] == false){ //判重
visited[t] = true; //状态标记
p.t = ptr.t + 1;
q.push(p);
}
}
}
if(i == 1){ //s给y倒
if(ptr.y < m && ptr.s > 0){
if(ptr.s <= m - ptr.y){
p.y = ptr.y + ptr.s;
p.s = 0;
p.x = ptr.x;
}
else{
p.s = ptr.s - (m - ptr.y);
p.y = m;
p.x = ptr.x;
}
int t = p.s*10000 + p.x*100 + p.y;
if(visited[t] == false){
visited[t] = true;
p.t = ptr.t + 1;
q.push(p);
}
}
}
if(i == 2){ //x给s倒
p.x = 0;
p.s = ptr.x + ptr.s;
p.y = ptr.y;
int t = p.s*10000 + p.x*100 + p.y;
if(visited[t] == false){
visited[t] = true;
p.t = ptr.t + 1;
q.push(p);
}
}
if(i == 3){ //y给s倒
p.x = ptr.x;
p.s = ptr.y + ptr.s;
p.y = 0;
int t = p.s*10000 + p.x*100 + p.y;
if(visited[t] == false){
visited[t] = true;
p.t = ptr.t + 1;
q.push(p);
}
}
if(i == 4){ //x给y倒
if(ptr.y < m && ptr.x > 0){ //y没满
if(ptr.x <= m - ptr.y){ //x中的饮料无法填满y
p.y = ptr.x + ptr.y;
p.x = 0;
p.s = ptr.s;
}
else{
p.x = ptr.x - (m - ptr.y);
p.y = m;
p.s = ptr.s;
}
int t = p.s*10000 + p.x*100 + p.y;
if(visited[t] == false){
visited[t] = true;
p.t = ptr.t + 1;
q.push(p);
}
}
}
if(i == 5){ //y给x倒
if(ptr.x < n && ptr.y > 0){
if(ptr.y <= n - ptr.x){
p.x = ptr.x + ptr.y;
p.y = 0;
p.s = ptr.s;
}
else{
p.y = ptr.y - (n - ptr.x);
p.x = n;
p.s = ptr.s;
}
int t = p.s*10000 + p.x*100 + p.y;
if(visited[t] == false){
visited[t] = true;
p.t = ptr.t + 1;
q.push(p);
}
}
}
}
}
printf("NO\n");
}
int main()
{
int s,m,n;
while(~scanf("%d%d%d",&s,&n,&m)){
if(s == 0 && n == 0 && m == 0){
break;
}
memset(visited,false,sizeof(visited));
while(!q.empty()){
q.pop();
}
node p;
p.s = s;p.x = 0;p.y = 0;p.t = 0;
int t = p.s*10000 + p.x*100 + p.y;
visited[t] = true;
q.push(p);
bfs(s,n,m);
}
return 0;
}
HDU2612
搜索第九题每个人都单独出发一次bfs,将距离记录在二维数组中,最后找最小
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <string>
#define maxs 201
#define INF 999999
using namespace std;
char map[maxs][maxs];
int visited[maxs][maxs];
int b[maxs][maxs];
int m,n,y_x,y_y;
int m_x,m_y;
struct Node{
int x,y,step;
};
int dx[4] = {1,-1,0,0};
int dy[4] = {0,0,-1,1};
queue<Node>q;
void BFS()
{
while(!q.empty()){
Node p = q.front();
q.pop();
if(map[p.x][p.y] == '@'){
b[p.x][p.y] += p.step;
}
for(int i = 0;i < 4;i++){
int nx = p.x + dx[i];
int ny = p.y + dy[i];
if(nx<0||nx>=m||ny<0||ny>=n||map[nx][ny] == '#'||visited[nx][ny]==1){
continue;
}
Node ptr;
ptr.x = nx;ptr.y = ny;ptr.step = p.step + 1;
visited[ptr.x][ptr.y] = 1;
q.push(ptr);
}
}
}
int main()
{
while(cin>>m>>n){
memset(b,0,sizeof(b));
for(int i = 0; i < m; i++){
for(int j = 0;j < n; j++){
cin>>map[i][j];
visited[i][j] = 0;
if(map[i][j]=='Y'){
y_x = i;y_y = j;
}
if(map[i][j]=='M'){
m_x = i;m_y = j;
}
}
}
while(!q.empty()){
q.pop();
}
Node start;
start.x = y_x;start.y = y_y;start.step = 0;
q.push(start);
visited[start.x][start.y] = 1;
BFS();
while(!q.empty()){
q.pop();
}
memset(visited,0,sizeof(visited));
start.x = m_x;start.y = m_y;start.step = 0;
q.push(start);
visited[start.x][start.y] = 1;
BFS();
int Min = INF;
for(int i = 0;i < m;i++){
for(int j = 0;j < n;j++){
if(b[i][j]!=0){
Min = min(Min,b[i][j]);
}
}
}
cout<<Min*11<<endl;
}
return 0;
}
HDU1195
搜索第十题数字搜索,和上面一样找好转移状态
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
struct Node{
int x,step;
bool operator <(const Node& s)const{
return s.step < step;
}
};
priority_queue<Node>q;
int a[4];
bool visited[10001];
void new_set()
{
while(!q.empty()){
q.pop();
}
memset(visited,false,sizeof(visited));
}
void bfs(int x,int y)
{
Node p;
p.x = x;p.step = 0;
visited[x] = true;
q.push(p);
while(!q.empty()){
p = q.top();
q.pop();
if(p.x == y){
cout<<p.step<<endl;
break;
}
for(int i = 0;i <= 10;i++){
a[0] = p.x/1000;a[1] = p.x/100%10;a[2] = p.x/10%10;a[3] = p.x%10;
if(i <= 2){
int t = a[i];
a[i] = a[i+1];
a[i+1] = t;
}
else if(i <= 6){
a[(i+1)%4] += 1;
if(a[(i+1)%4] > 9){
a[(i+1)%4] = 1;
}
}
else if(i <= 10){
a[(i+1)%4] -= 1;
if(a[(i+1)%4] <= 0){
a[(i+1)%4] = 9;
}
}
Node ptr;
ptr.x = a[0]*1000+a[1]*100+a[2]*10+a[3];
if(visited[ptr.x] == false){
ptr.step = p.step + 1;
visited[ptr.x] = true;
q.push(ptr);
}
}
}
}
int main()
{
int n;
cin>>n;
while(n--){
int x,y;
cin>>x>>y;
new_set();
bfs(x,y);
}
return 0;
}
HDU1180
搜索第十一题,楼梯会旋转,应该假设你走完一步之后楼梯立马旋转一个方向。然后可以原地等一分钟等楼梯转个方向,第一次卡死在这里。bfs + priotity_queue
#include <iostream>
#include <cstring>
#include <algorithm>
#include <string>
#include <queue>
using namespace std;
const int maxn = 25;
struct Node{
int x,y,step;
bool operator < (const Node &s)const{
return s.step < step;
}
};
priority_queue<Node>q;
char map[maxn][maxn];
int visited[maxn][maxn];
int dx[] = {1,-1,0,0};
int dy[] = {0,0,1,-1};
int m,n;
void new_set()
{
while(!q.empty()){
q.pop();
}
memset(visited,0,sizeof(visited));
}
bool check(int x,int y)
{
if(x < 0 || x >= m || y < 0 || y >= n || map[x][y] == '*' || visited[x][y] == 1){
return false;
}
else{
return true;
}
}
void bfs()
{
Node p,ptr;
while(!q.empty()){
p = q.top();
q.pop();
if(map[p.x][p.y] == 'T'){
cout<<p.step<<endl;
break;
}
for(int i = 0;i < 4;i++){
ptr.x = p.x + dx[i];
ptr.y = p.y + dy[i];
if(check(ptr.x,ptr.y) == false){
continue;
}
if((map[ptr.x][ptr.y] == '|' && p.step % 2 == 0)
|| (map[ptr.x][ptr.y] == '-' && p.step % 2 == 1)){
if(dx[i] != 0){
ptr.x += dx[i];
ptr.y += dy[i];
if(check(ptr.x,ptr.y) == false){
continue;
}
ptr.step = p.step + 1;
visited[ptr.x][ptr.y] = 1;
q.push(ptr);
}
else{
ptr.x = p.x;
ptr.y = p.y;
ptr.step = p.step + 1;
q.push(ptr);
}
}
else if((map[ptr.x][ptr.y] == '|' && p.step % 2 == 1)
|| (map[ptr.x][ptr.y] == '-' && p.step % 2 == 0)){
if(dy[i] != 0){
ptr.x += dx[i];
ptr.y += dy[i];
if(check(ptr.x,ptr.y) == false){
continue;
}
ptr.step = p.step + 1;
visited[ptr.x][ptr.y] = 1;
q.push(ptr);
}
else{
ptr.x = p.x;
ptr.y = p.y;
ptr.step = p.step + 1;
q.push(ptr);
}
}
else{
visited[ptr.x][ptr.y] = 1;
ptr.step = p.step + 1;
q.push(ptr);
}
}
}
}
int main()
{
int x,y;
while(cin>>m>>n){
for(int i = 0;i < m;i++){
for(int j = 0;j < n;j++){
cin>>map[i][j];
if(map[i][j] == 'S'){
x = i;y = j;
}
}
}
new_set();
Node start;
start.x = x;start.y = y;start.step = 0;
q.push(start);
visited[x][y] = 1;
bfs();
}
return 0;
}
HDU2717
一维数字搜索,bfs + priority_queue,优不优先队列都可以做
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;
const int maxn = 1e5+10;
struct node{
int x; //当前点的坐标
int t; //时间
int z; //差值绝对值
bool operator <(const node s)const{
if(s.t == t){
return s.z < z;
}
else{
return s.t < t;
}
}
};
priority_queue<node>q;
bool visited[maxn];
void bfs(int k)
{
while(!q.empty()){
node p = q.top(),ptr;
q.pop();
if(p.x == k){
printf("0\n");
return ;
}
for(int i = 0;i < 3;i++){
if(i == 0){
ptr.x = p.x + 1;
}
if(i == 1){
ptr.x = p.x - 1;
}
if(i == 2){
ptr.x = p.x * 2;
}
if(ptr.x < 0 || ptr.x > maxn || visited[ptr.x] == true){
continue;
}
ptr.t = p.t + 1;
if(ptr.x == k){
printf("%d\n",ptr.t);
return ;
}
ptr.z = abs(ptr.x - k);
visited[ptr.x] = true;
q.push(ptr);
}
}
}
int main()
{
int n,k;
while(~scanf("%d%d",&n,&k)){
memset(visited,false,sizeof(visited));
while(!q.empty()){
q.pop();
}
node p;
p.x = n;p.t = 0;p.z = abs(k-n);
q.push(p);
visited[n] = true;
bfs(k);
}
return 0;
}
HDU1973
还是一个开锁问题bfs + queue + 埃筛
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn = 1e5+5;
bool prime[maxn];
bool visited[maxn];
struct node{
int num,t;
};
void getprime()
{
memset(prime,true,sizeof(prime));
prime[0] = prime[1] = false;
for(int i = 2;i < maxn;i++){
if(prime[i]){
for(int j = 2*i;j < maxn;j += i){
prime[j] = false;
}
}
}
}
queue<node>q;
void bfs(int y)
{
while(!q.empty()){
node ptr = q.front(),p;
q.pop();
if(ptr.num == y){
printf("%d\n",ptr.t);
return ;
}
int a[4];
a[0] = ptr.num/1000;a[1] = ptr.num/100%10;
a[2] = ptr.num/10%10;a[3] = ptr.num%10;
// cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<" "<<a[3]<<endl;
for(int i = 0;i < 4;i++){
for(int j = 1;j <= 10;j++){
if(i == 0){
int t = (a[0] + j)%10;
int x = t*1000+a[1]*100+a[2]*10+a[3];
if(t != a[0] && t != 0 && prime[x] == true && visited[x] == false){
p.num = x;p.t = ptr.t + 1;
visited[x] = true;
q.push(p);
}
}
if(i == 1){
int t = (a[1] + j)%10;
int x = a[0]*1000+t*100+a[2]*10+a[3];
if(t != a[1] && prime[x] == true && visited[x] == false){
p.num = x;p.t = ptr.t + 1;
visited[x] = true;
q.push(p);
}
}
if(i == 2){
int t = (a[2] + j)%10;
int x = a[0]*1000+a[1]*100+t*10+a[3];
if(t != a[2] && prime[x] == true && visited[x] == false){
p.num = x;p.t = ptr.t + 1;
visited[x] = true;
q.push(p);
}
}
if(i == 3){
int t = (a[3] + j)%10;
int x = a[0]*1000+a[1]*100+a[2]*10+t;
if(t != a[3] && prime[x] == true && visited[x] == false){
p.num = x;p.t = ptr.t + 1;
visited[x] = true;
q.push(p);
}
}
}
}
}
}
int main()
{
getprime();
int t,x,y;
scanf("%d",&t);
while(t--){
scanf("%d%d",&x,&y);
node p;
memset(visited,false,sizeof(visited));
while(!q.empty()){
q.pop();
}
p.num = x;p.t = 0;
q.push(p);
visited[x] = true;
bfs(y);
}
return 0;
}
POJ3414
bfs + queue + 路径打印,还是倒水问题。比杭电那个要简单一点。
#include <iostream>
#include <cstring>
#include <queue>
#include <cstdio>
#include <algorithm>
using namespace std;
struct node{
int x,y,t;
int f[200];
};
queue<node>q;
bool visited[10000];
void bfs(int a,int b,int c)
{
while(!q.empty()){
node ptr = q.front(),p;
q.pop();
if(ptr.x == c || ptr.y == c){
printf("%d\n",ptr.t);
for(int i = 1;i <= ptr.t;i++){
if(ptr.f[i] == 1){
printf("FILL(1)\n");
}
if(ptr.f[i] == 2){
printf("FILL(2)\n");
}
if(ptr.f[i] == 3){
printf("DROP(1)\n");
}
if(ptr.f[i] == 4){
printf("DROP(2)\n");
}
if(ptr.f[i] == 5){
printf("POUR(1,2)\n");
}
if(ptr.f[i] == 6){
printf("POUR(2,1)\n");
}
}
return ;
}
p = ptr;
for(int i = 0;i < 6;i++){
if(i == 0){ //给a加满
p.x = a;
p.y = ptr.y;
int t = p.x*100+p.y;
if(visited[t] == false){
p.t = ptr.t + 1;
p.f[p.t] = 1;
visited[t] = true;
q.push(p);
}
}
if(i == 1){ //给b加满
p.x = ptr.x;
p.y = b;
int t = p.x*100+p.y;
if(visited[t] == false){
p.t = ptr.t + 1;
p.f[p.t] = 2;
visited[t] = true;
q.push(p);
}
}
if(i == 2){ //把a倒掉
p.x = 0;
p.y = ptr.y;
int t = p.x*100+p.y;
if(visited[t] == false){
p.t = ptr.t + 1;
p.f[p.t] = 3;
visited[t] = true;
q.push(p);
}
}
if(i == 3){ //把b倒掉
p.x = ptr.x;
p.y = 0;
int t = p.x*100+p.y;
if(visited[t] == false){
p.t = ptr.t + 1;
p.f[p.t] = 4;
visited[t] = true;
q.push(p);
}
}
if(i == 4){ //a给b倒
if(ptr.y < b){
if(ptr.x <= b - ptr.y){
p.x = 0;
p.y = ptr.x + ptr.y;
}
else{
p.x = ptr.x - (b - ptr.y);
p.y = b;
}
int t = p.x*100+p.y;
if(visited[t] == false){
p.t = ptr.t + 1;
p.f[p.t] = 5;
visited[t] = true;
q.push(p);
}
}
}
if(i == 5){ //b给a倒
if(ptr.x < a){
if(ptr.y <= a - ptr.x){
p.x = ptr.x + ptr.y;
p.y = 0;
}
else{
p.x = a;
p.y = ptr.y - (a - ptr.x);
}
int t = p.x*100+p.y;
if(visited[t] == false){
p.t = ptr.t + 1;
p.f[p.t] = 6;
visited[t] = true;
q.push(p);
}
}
}
}
}
printf("impossible\n");
}
int main()
{
int a,b,c;
while(~scanf("%d%d%d",&a,&b,&c)){
while(!q.empty()){
q.pop();
}
node p;
p.x = 0;p.y = 0;p.t = 0;
memset(p.f,0,sizeof(p.f));
memset(visited,0,sizeof(visited));
q.push(p);
bfs(a,b,c);
}
return 0;
}
POJ2251
简简单单一个三维迷宫,bfs + queue
#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
struct Node{
int x,y,z,step;
};
const int maxn = 35;
int dx[] = {1,-1,0,0,0,0};
int dy[] = {0,0,1,-1,0,0};
int dz[] = {0,0,0,0,1,-1};
char map[maxn][maxn][maxn];
queue<Node>q;
int x,y,z;
int bfs()
{
while(!q.empty()){
Node ptr = q.front(),p;
q.pop();
for(int i = 0;i < 6;i++){
p.x = ptr.x + dx[i];
p.y = ptr.y + dy[i];
p.z = ptr.z + dz[i];
if(p.x < 0 || p.x >= x || p.y < 0 || p.y >= y || p.z < 0 || p.z >= z
|| map[p.x][p.y][p.z] == '#'){
continue;
}
p.step = ptr.step + 1;
if(map[p.x][p.y][p.z] == 'E'){
return p.step;
}
map[p.x][p.y][p.z] = '#';
q.push(p);
}
}
return -1;
}
int main()
{
while(~scanf("%d%d%d",&x,&y,&z)){
int start_x,start_y,start_z;
if(x == 0 && y == 0 && z == 0){
break;
}
int flag = 0;
for(int i = 0;i < x;i++){
for(int j = 0;j < y;j++){
scanf("%s",map[i][j]);
if(flag == 1){
continue;
}
int len = strlen(map[i][j]);
for(int k = 0;k < len;k++){
if(map[i][j][k] == 'S'){
start_x = i;start_y = j;start_z = k;
flag = 1;
break;
}
}
}
}
while(!q.empty()){
q.pop();
}
Node start;
start.x = start_x;start.y = start_y;
start.z = start_z;start.step = 0;
q.push(start);
int ans = bfs();
if(ans == -1){
printf("Trapped!\n");
}
else{
printf("Escaped in %d minute(s).\n",ans);
}
}
return 0;
}
最后一道可能交不了UVA11624,可以去VJ上交。
这道题应该是和前面HDU2612差不多,先让火跑bfs把到达每一块空地的时间存下来,然后让人去跑bfs看看能不能比火先到这个点,如果能就可以过去,如果人走到这里比火还慢,对不起等着被烧死。注意有多个起火点,WA了一发不冤。
#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int inf = 1e9;
const int maxn = 1050;
struct node{
int x,y;
int s;
};
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};
char map[maxn][maxn];
bool visited[maxn][maxn];
int sum[maxn][maxn];
queue<node> q;
void clear_queue()
{
memset(visited,false,sizeof(visited));
while(!q.empty()){
q.pop();
}
}
void bfs_fire(int m,int n)
{
while(!q.empty()){
node ptr = q.front(),p;
q.pop();
for(int i = 0;i < 4;i++){
p.x = ptr.x + dx[i];
p.y = ptr.y + dy[i];
p.s = ptr.s + 1;
if(p.x < 0 || p.x >= m || p.y < 0 || p.y >= n || map[p.x][p.y] == 'F'
|| map[p.x][p.y] == '#' || visited[p.x][p.y]){
continue;
}
sum[p.x][p.y] = p.s;
visited[p.x][p.y] = true;
q.push(p);
}
}
}
int bfs_person(int m,int n)
{
while(!q.empty()){
node ptr = q.front(),p;
q.pop();
if(ptr.x == 0 || ptr.y == 0 || ptr.x == m-1 || ptr.y == n-1){
return ptr.s + 1;
}
for(int i = 0;i < 4;i++){
p.x = ptr.x + dx[i];
p.y = ptr.y + dy[i];
p.s = ptr.s + 1;
if(map[p.x][p.y] == '#' || map[p.x][p.y] == 'F' || p.s >= sum[p.x][p.y] || visited[p.x][p.y]){
continue;
}
visited[p.x][p.y] = true;
q.push(p);
}
}
return -1;
}
int main()
{
int t,m,n;
node p;
cin>>t;
while(t--){
clear_queue();
cin>>m>>n;
int p_x,p_y;
for(int i = 0;i < m;i++){
for(int j = 0;j < n;j++){
cin>>map[i][j];
if(map[i][j] == 'J'){
p_x = i;p_y = j;
}
if(map[i][j] == 'F'){
p.x = i;p.y = j;p.s = 0;
visited[p.x][p.y] = true;
q.push(p);
}
sum[i][j] = inf;
}
}
bfs_fire(m,n);
clear_queue();
p.x = p_x;p.y = p_y;p.s = 0;
visited[p.x][p.y] = true;
q.push(p);
int ans = bfs_person(m,n);
if(ans == -1){
printf("IMPOSSIBLE\n");
}
else{
printf("%d\n",ans);
}
}
return 0;
}
HDU1175
bfs+queue,拐弯问题。先一直死走一个方向走完就一定要拐弯数+1,这题和上面那个挺像的。第二次接触拐弯问题在WA两发情况下AC了,开始两发考虑的不全
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int maxn = 1005;
struct info{
int x,y;
int s;
};
int map[maxn][maxn];
bool visited[maxn][maxn];
int dx[] = {1,-1,0,0};
int dy[] = {0,0,-1,1};
queue<info>q;
int n,m;
int check(int x,int y)
{
if(x >= 1 && x <= n && y >= 1 && y <= m){
return true;
}
else{
return false;
}
}
int bfs(int x,int y,int a,int b,int num)
{
info ptr,p;
ptr.x = x;ptr.y = y;ptr.s = -1;
visited[x][y] = true;
q.push(ptr);
while(!q.empty()){
ptr = q.front();
q.pop();
if(ptr.s > 2){ //大于2的拐弯直接掐掉,我感觉应该加入优先队列优化。
continue;
}
if(ptr.x == a && ptr.y == b){ //这里可以删掉了
return 1;
}
int sk = ptr.s + 1;
for(int i = 0;i < 4;i++){
p.x = ptr.x + dx[i];
p.y = ptr.y + dy[i];
while(check(p.x,p.y) == true){
if(visited[p.x][p.y] == false){
if(p.x == a && p.y == b){
if(sk <= 2){ //这个点是终点可以还要判断能不能拐弯数是不是不超过2
return 1; //因为上面只是筛掉了大于2的,等于2的没有筛掉
}
}
else if(map[p.x][p.y] == 0){ //如果不是终点但是是空点可以走,入队
visited[p.x][p.y] = true;
p.s = sk;
q.push(p);
}
}
if(map[p.x][p.y] != 0){ //如果上一个点不是终点又不是空点这个方向就不用一直走了
break;
}
p.x += dx[i];
p.y += dy[i];
}
}
}
return -1;
}
void clear_set()
{
memset(visited,false,sizeof(visited));
while(!q.empty()){
q.pop();
}
}
int main()
{
while(~scanf("%d%d",&n,&m) && n && m){
memset(map,0,sizeof(map));
for(int i = 1;i <= n;i++){
for(int j = 1;j <= m;j++){
scanf("%d",&map[i][j]);
}
}
int q;
scanf("%d",&q);
while(q--){
int x,y,a,b;
scanf("%d%d%d%d",&x,&y,&a,&b);
clear_set();
if(map[x][y] != map[a][b] || !map[x][y] || (x == a && y == b)){ //小小的剪枝
printf("NO\n");
continue;
}
int ans = bfs(x,y,a,b,map[x][y]);
if(ans == -1){
printf("NO\n");
}
else{
printf("YES\n");
}
}
}
return 0;
}
基础bfs搜索就这样了,当然还有难的,需要结合状态压缩等等目前自己还不会,加油~