BFS小结

hdu 1026 Ignatius and the Princess I

需要记录路径,别的地方就没什么难的了。

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define N 105
int mark[N][N],vis[N][N];
int n,m;
char s[N];
int cnt;
int dir[4][2]={{0,1},{1,0},{-1,0},{0,-1}};
struct node
{
    int x,y;
    int cnt;
    friend bool operator<(node a,node b)
    {
        return a.cnt>b.cnt;
    };
}q[N*N];
struct point
{
    int prex,prey;
}ans[N][N];
int judge(int x,int y)
{
    if(x>=1&&x<=m&&y>=1&&y<=n&&mark[x][y]!=-1&&vis[x][y]==0) return 1;
    return 0;
}
int BFS()
{
    node cur,next;
    cur.x=1;cur.y=1;cur.cnt=0;vis[1][1]=1;
    priority_queue<node>q;
    q.push(cur);
    while(!q.empty())
    {
        cur=q.top();
        q.pop();
        for(int i=0;i<4;i++)
        {
            next.cnt=cur.cnt+1;
            next.x=cur.x+dir[i][0];
            next.y=cur.y+dir[i][1];
            if(judge(next.x,next.y))
            {
                if(mark[next.x][next.y]!=0) next.cnt+=mark[next.x][next.y];
                vis[next.x][next.y]=1;
                ans[next.x][next.y].prex=cur.x;ans[next.x][next.y].prey=cur.y;
                if(next.x==m&&next.y==n) return next.cnt;
                q.push(next);
            }
        }
    }
    return -1;
}
void print(int x,int y)
{
    if(x==1&&y==1) return ;
    print(ans[x][y].prex,ans[x][y].prey);
    printf("%ds:(%d,%d)->(%d,%d)\n",cnt++,ans[x][y].prex-1,ans[x][y].prey-1,x-1,y-1);
    if(mark[x][y]==0) return ;
    while(mark[x][y]--) printf("%ds:FIGHT AT (%d,%d)\n",cnt++,x-1,y-1);
    return ;
}
int main()
{
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        getchar();
        for(int i=1;i<=m;i++)
        {
            gets(s+1);
            for(int j=1;j<=n;j++)
            {
                if(s[j]=='.') mark[i][j]=0;
                else if(s[j]=='X') mark[i][j]=-1;
                else mark[i][j]=s[j]-'0';
            }
        }
        int answer;
        memset(vis,0,sizeof(vis));
        memset(ans,0,sizeof(ans));
        answer=BFS();
        if(answer==-1) printf("God please help our poor hero.\n");
        else
        {
            printf("It takes %d seconds to reach the target position, let me show you the way.\n",answer);
            cnt=1;
            print(m,n);
        }
        printf("FINISH\n");
    }
    return 0;
}
hdu 3316 Mine sweeping

做这道题的时候犯了三个错误,一道不难的题结果wa了很多次才A掉。
一、将ans数组的初值设为0,但是在输出的时候如果ans[i][j]为0,就输出‘".",这个很二。
二、每次搜索一个点的时候,应该对它周围八个点进行检查,我还是习惯性的检查了四个点。
三、忘了在输出"it is a beiju!"后面双换行,这个错误贡献了很多个PE。
思路很直白,对于搜到的每一个点检查周围是否有地雷,如果有的话,记录地雷的数量,并且不对当前的点进行搜索,否则对当前点开始搜索。
#include<stdio.h>
#include<string.h>
#define N 105
int mark[N][N],vis[N][N],ans[N][N];
int dir[8][2]={{1,0},{0,1},{-1,0},{0,-1},{-1,-1},{-1,1},{1,-1},{1,1}};
int n,x,y;
char s[N];
struct node
{
    int x,y;
}q[N*N];
int fun(int x,int y)
{
    if(x>=1&&x<=n&&y>=1&&y<=n) return 1;
    return 0;
}
int judge(int x,int y)
{
    int sum=0;
    if(fun(x-1,y-1)&&mark[x-1][y-1]==-1) sum++;
    if(fun(x-1,y)&&mark[x-1][y]==-1) sum++;
    if(fun(x-1,y+1)&&mark[x-1][y+1]==-1) sum++;
    if(fun(x,y-1)&&mark[x][y-1]==-1) sum++;
    if(fun(x,y+1)&&mark[x][y+1]==-1) sum++;
    if(fun(x+1,y-1)&&mark[x+1][y-1]==-1) sum++;
    if(fun(x+1,y)&&mark[x+1][y]==-1) sum++;
    if(fun(x+1,y+1)&&mark[x+1][y+1]==-1) sum++;
    return sum;
}
void BFS()
{
    node cur,next;
    int head,tail;
    head=tail=0;
    cur.x=x;cur.y=y;
    vis[cur.x][cur.y]=1;
    q[tail++]=cur;
    while(head!=tail)
    {
        cur=q[head++];
        ans[cur.x][cur.y]=judge(cur.x,cur.y);
        if(ans[cur.x][cur.y]!=0) continue;
        for(int i=0;i<8;i++)
        {
            next.x=cur.x+dir[i][0];
            next.y=cur.y+dir[i][1];
            if(fun(next.x,next.y)&&vis[next.x][next.y]==0)
            {
                vis[next.x][next.y]=1;
                q[tail++]=next;
            }
        }
    }
    return ;
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        getchar();
        for(int i=1;i<=n;i++)
        {
            gets(s+1);
            for(int j=1;j<=n;j++)
            {
                if(s[j]=='O') mark[i][j]=0;
                else if(s[j]=='X') mark[i][j]=-1;
            }
        }
        scanf("%d%d",&x,&y);
        x++;y++;
        if(mark[x][y]==-1)
        {
            printf("it is a beiju!\n\n");
            continue;
        }
        memset(vis,0,sizeof(vis));
        memset(ans,-1,sizeof(ans));
        BFS();
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(ans[i][j]==-1) printf(".");
                else printf("%d",ans[i][j]);
            }
            printf("\n");
        }
        printf("\n");
    }
    return 0;
}

 hdu 4308 Saving Princess claire_

这道题主要有两个问题。
一、解决内存大小的问题,这道题需要动态申请内存,如果直接开一个5000*5000的内存,会MLE。
二、题目数据有问题,我记录的cost用int提交wa,改为long long提交之后AC。但是题目保证最多5000个节点,每个节点的花费不超过10000,理论上最大花费是5*10^7,不会超int。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
using namespace std;
#define N 5005
typedef long long LL;
int n,m,k,cnt;
int **mark,**vis;
int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
int sx,sy;
char s[N];
struct node
{
    int x,y;
    LL cost;
    friend bool operator<(node a,node b)
    {
        return a.cost>b.cost;
    };
};
struct point
{
    int x,y;
}hash[N];
int judge(int x,int y)
{
    if(x<1||x>m||y<1||y>n) return 0;
    if(vis[x][y]==1) return 0;
    if(mark[x][y]==-1) return 0;
    return 1;
}
LL BFS()
{
    node cur,next;
    priority_queue<node>q;
    cur.x=sx;cur.y=sy;cur.cost=0;
    vis[cur.x][cur.y]=1;
    q.push(cur);
    while(!q.empty())
    {
       cur=q.top();
       q.pop();
       for(int i=0;i<4;i++)
       {
           next.cost=cur.cost;
           next.x=cur.x+dir[i][0];
           next.y=cur.y+dir[i][1];
           if(judge(next.x,next.y))
           {
               if(mark[next.x][next.y]==1) next.cost=cur.cost+k;
               vis[next.x][next.y]=1;
               if(mark[next.x][next.y]==2) return next.cost;
               q.push(next);
           }
       }
       if(mark[cur.x][cur.y]==10)
       {
           for(int i=0;i<cnt;i++)
           {
               next.x=hash[i].x;
               next.y=hash[i].y;
               next.cost=cur.cost;
               if(judge(hash[i].x,hash[i].y))
               {
                   vis[hash[i].x][hash[i].y]=1;
                   q.push(next);
               }
           }
       }
    }
    return -1;
}
int main()
{
    while(scanf("%d%d%d",&m,&n,&k)!=EOF)
    {
        getchar();
        mark=(int **)malloc((m+2)*sizeof(int *));
        for(int i=0;i<=m+1;i++) mark[i]=(int *)malloc((n+2)*sizeof(int));
        vis=(int **)malloc((m+2)*sizeof(int *));
        for(int i=0;i<=m+1;i++) vis[i]=(int *)malloc((n+2)*sizeof(int));
        cnt=0;
        for(int i=1;i<=m;i++)
        {
            gets(s+1);
            for(int j=1;j<=n;j++)
            {
                if(s[j]=='Y')
                {
                    mark[i][j]=0;
                    sx=i;
                    sy=j;
                }
                else if(s[j]=='C') mark[i][j]=2;
                else if(s[j]=='#') mark[i][j]=-1;
                else if(s[j]=='*') mark[i][j]=1;
                else if(s[j]=='P')
                {
                    mark[i][j]=10;
                    hash[cnt].x=i;hash[cnt].y=j;cnt++;
                }
            }
        }
        LL ans;
        memset(vis,0,sizeof(vis));
        ans=BFS();
        if(ans==-1) printf("Damn teoy!\n");
        else printf("%I64d\n",ans);
    }
    return 0;
}

hdu 2216  Game III

这道题错了很多遍,主要错在两个地方。
一、不能用scanf("%c",&c)读入,这个是题目的原因,之前遇到过几次这个问题,很烦!
二、我特么的没有对vis初始化!
题目思路倒是很简单,一个人的状态不好记录,两个人放一块儿就很容易记录了。

#include<stdio.h>
#include<string.h>
#define N 25
int mark[N][N],vis[N][N][N][N];
int m,n;
int dir[4][2]={{1,0},{0,1},{0,-1},{-1,0}};
char s[N][N];
struct node
{
    int x1,y1;
    int x2,y2;
    int cnt;
}q[500000],a;
int abs(int x)
{
    if(x<0) return -x;
    return x;
}
int fun(node a)
{
    int temp=abs(a.x1-a.x2)+abs(a.y1-a.y2);
    if(temp==1||temp==0) return 1;
    return 0;
}
int judge(int x,int y)
{
    if(x<1||x>m||y<1||y>n) return 0;
    if(mark[x][y]==-1) return 0;
    return 1;
}
int BFS()
{
    node cur,next;
    cur=a;
    vis[a.x1][a.y1][a.x2][a.y2]=1;
    if(fun(a)) return 0;
    int head,tail;
    head=tail=0;
    q[tail++]=cur;
    while(head!=tail)
    {
        cur=q[head++];
        next.cnt=cur.cnt+1;
        for(int i=0;i<4;i++)
        {
            next.x1=cur.x1+dir[i][0];
            next.y1=cur.y1+dir[i][1];
            if(judge(next.x1,next.y1))
            {
                next.x2=cur.x2+dir[3-i][0];
                next.y2=cur.y2+dir[3-i][1];
                if(!judge(next.x2,next.y2))
                {
                    next.x2=cur.x2;
                    next.y2=cur.y2;
                }
                if(vis[next.x1][next.y1][next.x2][next.y2]==1) continue;
                if(fun(next)) return next.cnt;
                q[tail++]=next;
                vis[next.x1][next.y1][next.x2][next.y2]=1;
            }
        }
    }
    return -1;
}
int main()
{
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        getchar();
        for(int i=1;i<=m;i++) gets(s[i]+1);
        a.cnt=0;
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=n;j++)
            {
                char c;
                c=s[i][j];
                if(c=='.') mark[i][j]=0;
                else if(c=='X') mark[i][j]=-1;
                else if(c=='Z')
                {
                    mark[i][j]=0;
                    a.x1=i;a.y1=j;
                }
                else if(c=='S')
                {
                    mark[i][j]=0;
                    a.x2=i;a.y2=j;
                }
            }
        }
        int ans;
        memset(vis,0,sizeof(vis));
        ans=BFS();
        if(ans==-1) printf("Bad Luck!\n");
        else printf("%d\n",ans);
    }
    return 0;
}

hdu 2531 Catch him

很好玩儿的一道题。
题目读完,麻烦的地方时怎么记录状态,开始的时候我没理解题目的意思,以为题目保证每个球员的是矩形,提交wa了两边之后重新读题才发现是一个二维的图形,什么图形都可以。所以干脆用一个数组记录状态,反正一个球员最多只占二十格,然后对于其中最小的点来标记是否到达过,之后就是普通的广搜了。

#include<stdio.h>
#include<string.h>
#define N 105
int mark[N][N],vis[N][N];
int s,e,m,n,k;
int minx,miny;
int dir[4][2]={{0,1},{1,0},{-1,0},{0,-1}};
struct point
{
    int x,y;
}a[21];
struct node
{
    int x,y;
    int cnt;
    point hash[21];
}q[N*N];
int judge(int x,int y)
{
    if(x<1||x>m) return -1;
    if(y<1||y>n) return -1;
    if(mark[x][y]==1) return 1;
	if(mark[x][y]==-1) return -1;
    return 0;
}
int BFS()
{
    int head,tail;
    node cur,next;
    head=tail=0;
    cur.x=minx;cur.y=miny;cur.cnt=0;
    for(int i=0;i<k;i++) cur.hash[i].x=a[i].x,cur.hash[i].y=a[i].y;
    vis[cur.x][cur.y]=1;
    q[tail++]=cur;
    while(head!=tail)
    {
        cur=q[head++];
        next.cnt=cur.cnt+1;
        for(int i=0;i<4;i++)
        {
            next.x=cur.x+dir[i][0];
            next.y=cur.y+dir[i][1];
            int flag=0;
            for(int j=0;j<k;j++)
            {
                next.hash[j].x=cur.hash[j].x+dir[i][0];
                next.hash[j].y=cur.hash[j].y+dir[i][1];
                int ans=judge(next.hash[j].x,next.hash[j].y);
                if(ans==-1)
                {
                    flag=-1;
                    break;
                }
                else if(ans==1) flag=1;
            }
            if(flag==-1) continue;
            if(vis[next.x][next.y]==1) continue;
            if(flag==1) return next.cnt;
            q[tail++]=next;vis[next.x][next.y]=1;
        }
    }
    return -1;
}
int main()
{
    while(scanf("%d%d",&m,&n),m+n)
    {
        getchar();
        k=0;
        minx=m+1;miny=n+1;
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=n;j++)
            {
                char c;
                scanf("%c",&c);
                if(c=='.') mark[i][j]=0;
                else if(c=='Q') mark[i][j]=1;
                else if(c=='O') mark[i][j]=-1;
                else
                {
					mark[i][j]=0;
                    a[k].x=i;a[k].y=j;k++;
                    if(i<minx) minx=i;
                    if(j<miny) miny=j;
                }
            }
            getchar();
        }
        int ans;
        memset(vis,0,sizeof(vis));
        ans=BFS();
        if(ans==-1) printf("Impossible\n");
        else printf("%d\n",ans);
    }
    return 0;
}

hdu 2209 翻纸牌游戏

看到题目的瞬间就想到了将所有纸牌的状态用二进制表示出来,20张牌刚好有大概一百万种状态,一百万种,从刚开始学BFS搜迷宫开始,差不多是我遇到的BFS里最经常碰见的状态数量了。
通过位运算来实现状态的转移,然后搜索所有的状态,最快搜索到的就是结果,如果搜索完所有能到达的状态仍然没有到达目标状态的时候,输出NO

#include<stdio.h>
#include<string.h>
#define N 25
char s[N];
int n;
int start,end;
int vis[(1<<20)+1];
struct node
{
    int x,cnt;
}q[(1<<N)+1];
int BFS()
{
    node cur,next;
    cur.x=start;
    cur.cnt=0;
    vis[start]=1;
    int head,tail;
    head=tail=0;
    q[tail++]=cur;
    while(head!=tail)
    {
        cur=q[head++];
        int temp=1;
        next.cnt=cur.cnt+1;
        for(int i=0;i<n;i++)
        {
            if(i<2) temp=(temp<<1)+1;
            else temp<<=1;
            if(i==n-1) temp&=(temp>>1);
            next.x=cur.x^temp;
            if(next.x==end) return next.cnt;
            if(vis[next.x]==0)
            {
                q[tail++]=next;
                vis[next.x]=1;
            }
        }
    }
    return -1;
}
int main()
{
    while(gets(s))
    {
        n=strlen(s);
        start=0;end=0;
        for(int i=0;i<n;i++) start=start*2+s[i]-'0';
        if(start==end)
        {
            printf("0\n");
            continue;
        }
        if(n==1&&start!=end)
        {
            printf("1\n");
            continue;
        }
        int ans;
        memset(vis,0,sizeof(vis));
        ans=BFS();
        if(ans==-1) printf("NO\n");
        else printf("%d\n",ans);
    }
    return 0;
}

hdu 4771 Stealing Harry Potter's Precious

用二进制来记录不同的宝物。

#include<stdio.h>
#include<string.h>
#include<queue>
#define N 105
using namespace std;
int vis[N][N][16],mark[N][N];
int n,m,k;
int sx,sy;
int dir[4][2]= {{1,0},{0,1},{-1,0},{0,-1}};
int temp;
struct node
{
    int x,y,k;
    int cnt;
};
int judge(int x,int y)
{
    if(x>=1&&x<=m&&y>=1&&y<=n&&mark[x][y]!=-1) return 1;
    return 0;
}
int bfs()
{
    queue<node>q;
    node cur,next;
    cur.x=sx;
    cur.y=sy;
    cur.cnt=0;
    if(mark[sx][sy]==2)
    {
        // mark[sx][sy]=1;
        cur.k=1;
    }
    else cur.k=0;
    vis[cur.x][cur.y][cur.k]=1;
    q.push(cur);
    while(!q.empty())
    {
        cur=q.front();
        q.pop();
        for(int i=0; i<4; i++)
        {
            next.x=cur.x+dir[i][0];
            next.y=cur.y+dir[i][1];
            next.cnt=cur.cnt+1;
            if(judge(next.x,next.y))
            {
                if(mark[next.x][next.y]>=1&&(mark[next.x][next.y]&cur.k)==0)
                {
                    next.k=cur.k+mark[next.x][next.y];
                    //mark[next.x][next.y]=1;
                }
                else next.k=cur.k;
                if(vis[next.x][next.y][next.k]==0)
                {
                    vis[next.x][next.y][next.k]=1;
                    if(next.k==temp-1) return next.cnt;
                    q.push(next);
                }
            }
        }
    }
    return -1;
}
int main()
{
    while(scanf("%d%d",&m,&n),n+m)
    {
        getchar();
        memset(mark,0,sizeof(mark));
        for(int i=1; i<=m; i++)
        {
            for(int j=1; j<=n; j++)
            {
                char c;
                scanf("%c",&c);
                if(c=='#') mark[i][j]=-1;
                else if(c=='.') mark[i][j]=0;
                else if(c=='@')
                {
                    mark[i][j]=0;
                    sx=i;
                    sy=j;
                }
            }
            getchar();
        }
        scanf("%d",&k);
        temp=1;
        for(int i=1; i<=k; i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            mark[x][y]=temp;
            temp*=2;
        }
        memset(vis,0,sizeof(vis));
        int ans;
        ans=bfs();
        printf("%d\n",ans);
    }
    return 0;
}

hdu 2579 Dating with girls(2)

两种解法吧。自己的思路:如果面对一面墙,并不是不能进入这面墙,而是要等一段儿时间,这段时间不能站在原地不动,还要四处转转。所以要检查能不能四处转转。如果能,并且这面墙还有k(k必须是奇数)段时间才能降下去,就可以进入,否则不能进入。并且不能从墙走到墙。为了每次输出时间最短的点,用优先队列维护。

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define N 105
int mark[N][N],vis[N][N];
int sx,sy,ex,ey;
int m,n,k;
struct node
{
    int x,y;
    int cnt;
    int flag;
    friend bool operator<(node a,node b)
    {
        return a.cnt>b.cnt;
    };
};
int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
int judge(int x,int y,int t)
{
    if(x>=1&&x<=m&&y>=1&&y<=n&&vis[x][y]==0)
        return 1;
    return 0;
}
int f(int x,int y)
{
    if(x>=1&&x<=m&&y>=1&&y<=n&&mark[x][y]==1)
        return 1;
    return 0;
}
int Find(int x,int y)
{
    int tx,ty;
    for(int i=0;i<4;i++)
    {
        tx=x+dir[i][0];
        ty=y+dir[i][1];
        if(f(tx,ty)) return 1;
    }
    return 0;
}
int bfs()
{
    priority_queue<node>q;
    node cur,next;
    cur.x=sx;cur.y=sy;cur.cnt=0;cur.flag=1;
    vis[sx][sy]=1;
    q.push(cur);
    while(!q.empty())
    {
        cur=q.top();
        if(cur.x==ex&&cur.y==ey) return cur.cnt;
        q.pop();
        for(int i=0;i<4;i++)
        {
           next.x=cur.x+dir[i][0];
           next.y=cur.y+dir[i][1];
           next.cnt=cur.cnt+1;
           if(judge(next.x,next.y,next.cnt))
           {
               if(mark[next.x][next.y]==1)
                    ;
               else if(mark[next.x][next.y]==2)
               {
                   if(cur.flag==2) continue;
                   if(next.cnt%k!=0)
                   {
                       int temp;
                       temp=cur.cnt%k;
                       temp=k-temp;
                       if(!Find(cur.x,cur.y)) continue;
                       if(cur.flag==2) continue;
                       if(temp%2==1) next.cnt=cur.cnt+temp;
                       else continue;
                   }
               }
               vis[next.x][next.y]=1;
               next.flag=mark[next.x][next.y];
               q.push(next);
           }
        }
    }
    return -1;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&m,&n,&k);
        getchar();
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=n;j++)
            {
                char c;
                scanf("%c",&c);
                if(c=='.') mark[i][j]=1;
                else if(c=='#') mark[i][j]=2;
                else if(c=='Y')
                {
                    mark[i][j]=1;
                    sx=i;sy=j;
                }
                else if(c=='G')
                {
                    mark[i][j]=1;
                    ex=i;ey=j;
                }
            }
            getchar();
        }
        int ans;
        memset(vis,0,sizeof(vis));
        ans=bfs();
        if(ans==-1) printf("Please give me another chance!\n");
        else printf("%d\n",ans);
    }
    return 0;
}

网上比较流行的思路:同一个点可以走多次,但是最多不能超过k次。在二维的基础上扩展一维,将二维的搜索转化为三维。

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define N 105
int vis[N][N][12],mark[N][N];
int n,m,k;
int sx,sy,ex,ey;
int dir[4][2]={{-1,0},{0,-1},{1,0},{0,1}};
struct node
{
    int x,y;
    int cnt;
};
int judge(int x,int y,int t)
{
    if(x>=1&&x<=m&&y>=1&&y<=n&&t>=0&&t<=10&&vis[x][y][t]==0)
    {
        if(mark[x][y]==1) return 1;
        else if(mark[x][y]==2&&t==0) return 1;
    }
    return 0;
}
int bfs()
{
    queue<node>q;
    node cur,next;
    cur.x=sx;cur.y=sy;cur.cnt=0;
    vis[sx][sy][0]=1;
    q.push(cur);
    while(!q.empty())
    {
        cur=q.front();
        q.pop();
        for(int i=0;i<4;i++)
        {
            next.x=cur.x+dir[i][0];
            next.y=cur.y+dir[i][1];
            next.cnt=cur.cnt+1;
            if(judge(next.x,next.y,next.cnt%k))
            {
                vis[next.x][next.y][next.cnt%k]=1;
                if(next.x==ex&&next.y==ey) return next.cnt;
                q.push(next);
            }
        }
    }
    return -1;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&m,&n,&k);
        getchar();
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=n;j++)
            {
                char c;
                scanf("%c",&c);
                if(c=='.') mark[i][j]=1;
                else if(c=='#') mark[i][j]=2;
                else if(c=='Y')
                {
                    mark[i][j]=1;
                    sx=i;sy=j;
                }
                else if(c=='G')
                {
                    mark[i][j]=1;
                    ex=i;ey=j;
                }
            }
            getchar();
        }
        memset(vis,0,sizeof(vis));
        int ans=bfs();
        if(ans==-1) printf("Please give me another chance!\n");
        else printf("%d\n",ans);
    }
    return 0;
}

hdu 4474 Yet Another Multiple Problem

对于一个数k,我们想知道给它加一个尾数a,即k*10+a能不能被n整除,我们没必要去记录k,我们需要记录的只是k%n的值,因为k%n*10+a能被10整除,那么k*10+a就一定能被10整除。而对于v(k%10),我们只能允许它入队一次。假如它可以入队多次,就会形成环。比如pre[5]=7,pre[7]=5,pre[5]=7……这样的话,我们就把需要搜索的点缩小到了1~n一共n个点,而n范围是1~10000,这么几个点搜完真是太随意了。
输出结果的时候卡我了一下,想了好久,用了一种很笨的方法输出了结果。看了看别人的输出方法,就是多开一个数组,瞬间代码就变得简单了许多。。。。

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define N 100005
int mark[15],pre[N],q[N];
int n,m;
void print(int x)
{
    if(x==0) return ;
    print(pre[x]);
    for(int i=0; i<10; i++)
    {
        if(mark[i]!=1&&(pre[x]*10+i)%n==x)
        {
            printf("%d",i);
            break;
        }
    }
    return ;
}
void BFS()
{
    int head,tail;
    head=tail=0;
    int t=n;
    int flag=0;
    while(t)
    {
        if(mark[t%10]==1)
        {
            flag=1;
            break;
        }
        t/=10;
    }
    if(!flag)
    {
        printf("%d\n",n);
        return ;
    }
    q[tail++]=0;
	pre[0]=0;
    while(head<tail)
    {
        int cur;
        cur=q[head++];
        for(int i=0; i<=9; i++)
        {
            if(mark[i]!=1)
            {
                int x;
                x=cur*10+i;
                if(x==0) continue;
                if(x%n==0)
                {
                    print(cur);
                    printf("%d\n",i);
                    return ;
                }
                int v;
                v=x%n;
                if(pre[v]==-1)
                {
                    q[tail++]=v;
                    pre[v]=cur;
                }
            }
        }
    }
    printf("-1\n");
    return ;
}
int main()
{
    int cnt=1;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(mark,0,sizeof(mark));
        for(int i=0; i<m; i++)
        {
            int x;
            scanf("%d",&x);
            mark[x]=1;
        }
        memset(pre,-1,sizeof(pre));
        printf("Case %d: ",cnt++);
        BFS();
    }
    return 0;
}

hdu 3713 Double Maze

这道题两个maze分开看的话每个点都可以到达多次,但是如果两个maze放在一块儿,将他们两个的状态作为一个状态来记录,那么这个状态就只能到达一次。比如说对于第一个maze中的1,3这个点和第二个maze中的2,4这个点,这两个点都可以到达很多次,但是第一个maze在1,3,同时第二个maze在2,4这种状态却只允许出现一次。这样这道题就变成了一个有6^4种状态的迷宫,看最快需要多久才能到达终点状态,并且输出字典序最小的。
将两个出发点放在一块儿当作起始状态,两个终点放在一块儿当作终点状态,做一次bfs,在每一个状态记录它的前驱状态。将四个方向按照字典序排序,这样搜索到的第一个终点就是字典序最小的方案,然后递归输出方案。
没有注意起点和终点可以是同一点,wa了许久。。。。

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define N 8
int mark[N][N][N][N];
int a[N][N],b[N][N];
int ans[10005];
int dir[4][4]= {{1,0,1,0},{0,-1,0,-1},{0,1,0,1},{-1,0,-1,0}};
int flag[4]= {2,1,4,8};
char s[4]= {'D','L','R','U'};
struct node
{
    int x,y;
    int xx,yy;
    int x1,y1,x2,y2;
} sa,sb,ea,eb,vis[N][N][N][N];
int judge(node c)
{
    if(mark[c.x][c.y][c.xx][c.yy]==1)
        return 0;
    if((a[c.x][c.y]&16)==0)
        return 0;
    if((b[c.xx][c.yy]&16)==0)
        return 0;
    return 1;
}
int bfs()
{
    queue<node>q;
    node cur,next;
    cur.x=sa.x;
    cur.y=sa.y;
    cur.xx=sb.x;
    cur.yy=sb.y;
    if(cur.x==ea.x&&cur.y==ea.y&&cur.xx==eb.x&&cur.yy==eb.y) return 0;
    mark[cur.x][cur.y][cur.xx][cur.yy]=1;
    q.push(cur);
    while(!q.empty())
    {
        cur=q.front();
        q.pop();
        for(int i=0; i<4; i++)
        {
            if((a[cur.x][cur.y]&flag[i])==0)
            {
                next.x=cur.x+dir[i][0];
                next.y=cur.y+dir[i][1];
            }
            else
            {
                next.x=cur.x;
                next.y=cur.y;
            }
            if((b[cur.xx][cur.yy]&flag[i])==0)
            {
                next.xx=cur.xx+dir[i][2];
                next.yy=cur.yy+dir[i][3];
            }
            else
            {
                next.xx=cur.xx;
                next.yy=cur.yy;
            }
            if(judge(next))
            {
                vis[next.x][next.y][next.xx][next.yy].x1=cur.x;
                vis[next.x][next.y][next.xx][next.yy].y1=cur.y;
                vis[next.x][next.y][next.xx][next.yy].x2=cur.xx;
                vis[next.x][next.y][next.xx][next.yy].y2=cur.yy;
                mark[next.x][next.y][next.xx][next.yy]=1;
                //    printf("%d %d %d %d %c %d %d %d %d\n",cur.x,cur.y,cur.xx,cur.yy,s[i],next.x,next.y,next.xx,next.yy);
                if(next.x==ea.x&&next.y==ea.y&&next.xx==eb.x&&next.yy==eb.y) return 0;
                q.push(next);
            }
        }
    }
    return 1;
}
void print(int x,int y,int xx,int yy)
{
    int tx,ty,txx,tyy;
    tx=x;
    ty=y;
    txx=xx;
    tyy=yy;
    if(x==sa.x&&y==sa.y&&xx==sb.x&&yy==sb.y) return ;
    x=vis[tx][ty][txx][tyy].x1;
    y=vis[tx][ty][txx][tyy].y1;
    xx=vis[tx][ty][txx][tyy].x2;
    yy=vis[tx][ty][txx][tyy].y2;
    print(x,y,xx,yy);
    for(int i=0; i<4; i++)
    {
        if((tx+dir[i][0]==x&&ty+dir[i][1]==y)||(txx+dir[i][2]==xx&&tyy+dir[i][3]==yy))
        {
            if(i==1) i=2;
            else if(i==2) i=1;
            else if(i==3) i=0;
            else if(i==0) i=3;
            printf("%c",s[i]);
            return ;
        }
    }
    return ;
}
int main()
{
    int T;
    scanf("%d",&T);
    int cnt=0;
    memset(a,0,sizeof(a));
    memset(b,0,sizeof(b));
    while(cnt<T)
    {
        if(cnt%2==0)
        {
            for(int i=1; i<=6; i++)
            {
                for(int j=1; j<=6; j++)
                {
                    scanf("%d",&a[i][j]);
                    if(a[i][j]&32)
                    {
                        sa.x=i;
                        sa.y=j;
                    }
                    if(a[i][j]&64)
                    {
                        ea.x=i;
                        ea.y=j;
                    }
                }
            }
        }
        else
        {
            for(int i=1; i<=6; i++)
            {
                for(int j=1; j<=6; j++)
                {
                    scanf("%d",&b[i][j]);
                    if(b[i][j]&32)
                    {
                        sb.x=i;
                        sb.y=j;
                    }
                    if(b[i][j]&64)
                    {
                        eb.x=i;
                        eb.y=j;
                    }
                }
            }
        }
        cnt++;
        if(cnt<2) continue;
        memset(vis,-1,sizeof(vis));
        memset(mark,0,sizeof(mark));
        if(bfs())
        {
            printf("-1\n");
            continue;
        }
        print(ea.x,ea.y,eb.x,eb.y);
        printf("\n");
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值