首页 > 代码库 > 小试牛刀-搜索基础入门(杭电五题)

小试牛刀-搜索基础入门(杭电五题)

 hdu 1241 Oil Deposits

水题,BFS,判断区域的块数。

代码清单:

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef pair<int,int>P;

int m,n;
char s[105][105];
int xy[8][2]={{0,-1},{-1,-1},{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1}};

void bfs(int x,int y){
    queue<P>q;
    s[x][y]='*';
    q.push(P(x,y));
    while(q.size()){
        P p=q.front(); q.pop();
        for(int i=0;i<8;i++){
            int xx=p.first+xy[i][0];
            int yy=p.second+xy[i][1];
            if(xx>=0&&xx<m&&yy>=0&&yy<n&&s[xx][yy]!='*'){
                s[xx][yy]='*';
                q.push(P(xx,yy));
            }
        }
    }
}

int main(){
    while(scanf("%d%d",&m,&n)!=EOF){
        if(m==0&&n==0) break;
        //memset(s,'\0',sizeof(s));
        for(int i=0;i<m;i++)
            scanf("%s",s[i]);
        int ans=0;
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(s[i][j]=='@'){
                    ans++;
                    bfs(i,j);
                }
            }
        }
        printf("%d\n",ans);
    }return 0;
}

hdu1312 Red and Black

水题,BFS(DFS),求可走点的总和。

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef pair<int,int>P;

int m,n;
int sx,sy;
int vis[25][25];
char s[25][25];
int xy[4][2]={{0,-1},{-1,0},{0,1},{1,0}};

int bfs(){
    int sum=0;
    queue<P>q;
    while(q.size()) q.pop();
    q.push(P(sx,sy));
    vis[sx][sy]=1;
    while(q.size()){
        P p=q.front();
        q.pop();
        sum++;
        for(int i=0;i<4;i++){
            int xx=p.first+xy[i][0];
            int yy=p.second+xy[i][1];
            if(xx>=0&&xx<n&&yy>=0&&yy<m&&s[xx][yy]!='#'&&!vis[xx][yy]){
                vis[xx][yy]=1;  //cout<<xx<<" "<<yy<<endl;
                q.push(P(xx,yy));
            }
        }
    }return sum;
}

int main(){
    while(scanf("%d%d",&m,&n)!=EOF){
        if(m==0&&n==0) break;
        for(int i=0;i<n;i++){
            scanf("%s",s[i]);
            for(int j=0;j<m;j++){
                if(s[i][j]=='@'){
                    sx=i;
                    sy=j;
                }
            }
        }
        memset(vis,0,sizeof(vis));
        printf("%d\n",bfs());
    }return 0;
}

hdu 1010 Tempter of the Bone

DFS,从中学到了奇偶性剪枝。

题意:迷宫中只有一扇门,且只在第K秒时开门,问能否走出迷宫。

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

int first;
int N,M,T;
int sx,sy;
int ex,ey;
char s[8][8];
int x[4]={1,-1,0,0};
int y[4]={0,0,-1,1};

void dfs(int X,int Y,int t)
{
    if(t==T){
        if(X==ex&&Y==ey)
            first=1;
        return ;
    }
    if(first) return ;
    int judge=abs(X-ex)+abs(Y-ey)-abs(t-T);  //奇偶性剪枝:judge<=0且为偶数才可以继续
    if(judge>0 || judge%2) return ;
    for(int i=0;i<4;i++){
        int xx=X+x[i];
        int yy=Y+y[i];
        if(xx>=0&&xx<N&&yy>=0&&yy<M&&s[xx][yy]!='X'){
            s[xx][yy]='X';
            dfs(xx,yy,t+1);
            s[xx][yy]='.';
        }
    }
}

int main()
{
    while(scanf("%d%d%d",&N,&M,&T)!=EOF){
        if(N==0&&M==0&&T==0) break;
        int pos=0;
        for(int i=0;i<N;i++){
            scanf("%s",s[i]);
            for(int j=0;j<M;j++){
                if(s[i][j]=='S'){
                    sx=i;
                    sy=j;
                }
                else if(s[i][j]=='D'){
                    ex=i;
                    ey=j;
                }
                else if(s[i][j]=='X'){
                    pos++;
                }
            }
        }
        if(N*M-pos<=T) printf("NO\n"); //可走的点数必须大于T
        else{
            first=0;
            s[sx][sy]='X';
            dfs(sx,sy,0);
            if(first) printf("YES\n");
            else      printf("NO\n");
        }
    }return 0;
}

 hdu 1242 Rescue

优先队列+BFS。注意救援有多个,所以以终点为起始点,只要走到一个最近的救援点即可。

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

struct edge{
    int x,y;
    int t;
    friend bool operator<(edge a,edge b){
        return a.t>b.t;
    }
};

int N,M;
int ex,ey,ok;
int vis[205][205];
char s[205][205];
int xy[4][2]={{0,-1},{-1,0},{0,1},{1,0}};

int bfs(){
    priority_queue<edge>q;
    while(q.size()) q.pop();
    edge p;
    p.x=ex; p.y=ey; p.t=0;
    vis[ex][ey]=1;
    q.push(p);
    while(q.size()){
        p=q.top();
        q.pop();
        if(s[p.x][p.y]=='r'){
            return p.t;
        }
        for(int i=0;i<4;i++){
            edge w;
            w.x=p.x+xy[i][0];
            w.y=p.y+xy[i][1];
            if(w.x>=0&&w.x<N&&w.y>=0&&w.y<M&&s[w.x][w.y]!='#'&&!vis[w.x][w.y]){

                w.t=p.t+1;
                if(s[w.x][w.y]=='x') w.t++;
                vis[w.x][w.y]=1;
                q.push(w);
            }
        }
    }
    return -1;
}

int main(){
    while(scanf("%d%d",&N,&M)!=EOF){
        for(int i=0;i<N;i++){
            scanf("%s",s[i]);
            for(int j=0;j<M;j++){
                if(s[i][j]=='a'){
                    ex=i;
                    ey=j;
                }
            }
        }
        memset(vis,0,sizeof(vis));
        int ans=bfs();
        if(ans!=-1) printf("%d\n",ans);
        else        printf("Poor ANGEL has to stay in the prison all his life.\n");
    }return 0;
}

hdu 1026  Ignatius and the Princess I

优先队列+BFS+路径还原。

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

struct edge
{
    int x,y;
    int t,r;
    friend bool operator<(edge c,edge d){
        return c.t>d.t;
    }
}a[10000],b[105][105];  //b数组记录路径

int N,M;
int vis[105][105];
char s[105][105];
int xy[4][2]={{0,-1},{-1,0},{0,1},{1,0}};
void bfs()
{
    priority_queue<edge>q;
    while(q.size()) q.pop();
    edge p,w;
    p.x=0; p.y=0; p.t=0,p.r=0;
    vis[0][0]=1;
    q.push(p);
    int first=0;
    while(q.size())
    {
        p=q.top(); q.pop();
        if(p.x==N-1&&p.y==M-1){
            first=1;
            break;
        }
        for(int i=0;i<4;i++){
            w.x=p.x+xy[i][0];
            w.y=p.y+xy[i][1];
            if(w.x>=0&&w.x<N&&w.y>=0&&w.y<M&&s[w.x][w.y]!='X'&&!vis[w.x][w.y]){
                b[w.x][w.y].x=p.x;
                b[w.x][w.y].y=p.y;
                w.t=p.t+1;
                w.r=p.r+1;
                vis[w.x][w.y]=1;
                if(s[w.x][w.y]!='.')
                    w.t=w.t+s[w.x][w.y]-'0';
                q.push(w);
            }
        }
    }
    if(first)
    {
        int k=1;
        int i=p.r-1,xx=p.x,yy=p.y;
        a[p.r].x=p.x; a[p.r].y=p.y;
        for(i=p.r-1;i>=0;i--){
            a[i].x=b[xx][yy].x;
            a[i].y=b[xx][yy].y;
            xx=a[i].x;
            yy=a[i].y;
        }
        printf("It takes %d seconds to reach the target position, let me show you the way.\n",p.t);

        for(int i=0;i<p.r;i++){
            printf("%ds:(%d,%d)->(%d,%d)\n",k++,a[i].x,a[i].y,a[i+1].x,a[i+1].y);
            if(s[a[i+1].x][a[i+1].y]!='.'&&s[a[i+1].x][a[i+1].y]!='X'){
                int tt=s[a[i+1].x][a[i+1].y]-'0';
                while(tt--) printf("%ds:FIGHT AT (%d,%d)\n",k++,a[i+1].x,a[i+1].y);
            }
        }
    }
    else printf("God please help our poor hero.\n");
    printf("FINISH\n");
}

int main()
{
    while(scanf("%d%d",&N,&M)!=EOF){
        for(int i=0;i<N;i++)
            scanf("%s",s[i]);
        memset(vis,0,sizeof(vis));
        bfs();
    }return 0;
}


小试牛刀-搜索基础入门(杭电五题)