POJ 3278&&2049&&3083

  这次的题目叫图的深度&&广度优先遍历。

  然后等我做完了题发现这是DFS&&BFS爆搜专题。

  3278:题目是经典的FJ,他要抓奶牛。他和牛(只有一头)在一条数轴上,他们都站在一个点上(坐标为0~1e5)。假设FJ的位置为x,他每次可以去x+1,x-1,x*2的地方。问他最少走几次才能抓到他的牛(牛不会动)。

  赤裸裸的BFS,注意判断是否越界(很容易RE)

  CODE

#include<cstdio>
#include<cstring>
using namespace std;
const int N=100000;
int q[N*3+10],step[N+5],n,k;
bool vis[N+5];
inline void read(int &x)
{
    x=0; char ch=getchar();
    while (ch<'0'||ch>'9') ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
}
int main()
{
    read(n); read(k);
    memset(vis,true,sizeof(vis));
    if (n>=k) printf("%d",n-k); else
    {
        int head=0,tail=1;
        q[1]=n; step[n]=0; vis[n]=0;
        while (head<tail)
        {
            int now=q[++head];
            if (now==k) { printf("%d",step[now]); break; }
            if (now+1<=N) if (vis[now+1]) vis[now+1]=0,q[++tail]=now+1,step[now+1]=step[now]+1;
            if (now-1>=0) if (vis[now-1]) vis[now-1]=0,q[++tail]=now-1,step[now-1]=step[now]+1;
            if (now*2<=N) if (vis[now*2]) vis[now*2]=0,q[++tail]=now*2,step[now*2]=step[now]+1;
        }
    }
    return 0;
}

 

  2049:一道迷宫BFS,和今年NOIP PJ T3 有点类似。题意可以百度翻译(这道题翻译的还是很好的,至少能看懂)

  因为他给出的是网格的边而不是点,所以要进行转化。

  我们用a[x][y][0]表示(x,y)右方向的边的属性(墙或门或空地),a[x][y][1]表示(x,y)上方向的边的属性(同理)

  建图玩了以后可以再连边跑SPFA或者直接松弛BFS(循环更新到每个点的的最小通过门数)

  最后提醒那个人有可能不在迷宫里,就直接输出0

  CODE

#include<cstdio>
#include<cmath>
using namespace std;
const int N=205,INF=1e9,fx[4]={0,1,-1,0},fy[4]={1,0,0,-1};
int a[N][N][2],f[N][N],q[N*N*10+10][2],n,m,i,j,x,y,d,t;
double s_x,s_y;
inline void read(int &x)
{
    x=0; char ch=getchar(); int flag=1;
    while (ch<'0'||ch>'9') { if (ch=='-') flag=-1; ch=getchar(); }
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    x*=flag;
}
int main()
{
    for (;;)
    {
        read(n); read(m);
        if (n==-1&&m==-1) break;
        for (i=0;i<N;++i)
        for (j=0;j<N;++j)
        f[i][j]=INF,a[i][j][0]=a[i][j][1]=2;
        for (i=1;i<=n;++i)
        {
            read(x); read(y); read(d); read(t);
            if (d) 
            {
                for (j=y;j<y+t;++j)
                a[x][j][1]=0;
            } else
            {
                for (j=x;j<x+t;++j)
                a[j][y][0]=0;
            }
        }
        for (i=1;i<=m;++i)
        {
            read(x); read(y); read(d);
            if (d) a[x][y][1]=1; else a[x][y][0]=1;
        }
        scanf("%lf%lf",&s_x,&s_y);
        x=floor(s_x); y=floor(s_y);
        if (x<0||y<0||x>199||y>199||(!n&&!m)) { puts("0"); continue; }
        int head=0,tail=1;
        q[1][0]=x; q[1][1]=y; f[x][y]=0;
        while (head<tail)
        {
            x=q[++head][0]; y=q[head][1];
            for (i=0;i<4;++i)
            {
                int xx=x+fx[i],yy=y+fy[i];
                if (xx<0||yy<0||xx>200||yy>200) continue;
                if (i==0)
                {
                    if (a[xx][yy][0]==2) if (f[xx][yy]>f[x][y]) q[++tail][0]=xx,q[tail][1]=yy,f[xx][yy]=f[x][y];
                    if (a[xx][yy][0]==1) if (f[xx][yy]>f[x][y]+1) q[++tail][0]=xx,q[tail][1]=yy,f[xx][yy]=f[x][y]+1;
                } 
                if (i==1)
                {
                    if (a[xx][yy][1]==2) if (f[xx][yy]>f[x][y]) q[++tail][0]=xx,q[tail][1]=yy,f[xx][yy]=f[x][y];
                    if (a[xx][yy][1]==1) if (f[xx][yy]>f[x][y]+1) q[++tail][0]=xx,q[tail][1]=yy,f[xx][yy]=f[x][y]+1;
                }
                if (i==2)
                {
                    if (a[x][y][1]==2) if (f[xx][yy]>f[x][y]) q[++tail][0]=xx,q[tail][1]=yy,f[xx][yy]=f[x][y];
                    if (a[x][y][1]==1) if (f[xx][yy]>f[x][y]+1) q[++tail][0]=xx,q[tail][1]=yy,f[xx][yy]=f[x][y]+1;
                }
                if (i==3)
                {
                    if (a[x][y][0]==2) if (f[xx][yy]>f[x][y]) q[++tail][0]=xx,q[tail][1]=yy,f[xx][yy]=f[x][y];
                    if (a[x][y][0]==1) if (f[xx][yy]>f[x][y]+1) q[++tail][0]=xx,q[tail][1]=yy,f[xx][yy]=f[x][y]+1;
                }
            }
        }
        if (f[0][0]==INF) puts("-1"); else printf("%d\n",f[0][0]);
    }
    return 0;
}

 

  3083:这是一道神坑题,完美的展示了爆搜的含义。

  题意是一个图,S起点,E终点,.是空地,#是墙不能走。问从S到E左优先和右优先以及最短步数是多少。

  DFS+BFS。BFS最短和简单,终点的DFS。

  因为他要求遵循左右的性质,所以方向数组的定义就很玄学了

  以左优先为例 如果现在的方向是↑,那么优先级就是←↑→↓,其他方向同理(能左转就左转,不能转就向右转再判断),右优先同理。

  因此预处理一下坐标的顺序就很水了。

  CODE

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N=45,
l[4][4]=
{
    {3,0,1,2},
    {0,1,2,3},
    {1,2,3,0},
    {2,3,0,1},
},
r[4][4]=
{
    {1,0,3,2},
    {2,1,0,3},
    {3,2,1,0},
    {0,3,2,1},
},
fx[4]={0,-1,0,1},fy[4]={-1,0,1,0};
char a[N][N];
int q[N*N*10+10][2],step[N][N],i,j,n,m,s_x,s_y,e_x,e_y,t,w,l_ans,r_ans,min_ans;
bool vis[N][N],flag;
inline void read(int &x)
{
    x=0; char ch=getchar();
    while (ch<'0'||ch>'9') ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
}
inline void l_DFS(int x,int y,int w,int s)
{
    if (flag) return;
    if (x==e_x&&y==e_y) { l_ans=s; flag=1; return; }
    for (int i=0;i<4;++i)
    {
        int xx=x+fx[l[w][i]],yy=y+fy[l[w][i]];
        if (xx<=0||yy<=0||xx>n||yy>m) continue;
        if (a[xx][yy]=='#') continue;
        l_DFS(xx,yy,l[w][i],s+1);
    }
}
inline void r_DFS(int x,int y,int w,int s)
{
    if (flag) return;
    if (x==e_x&&y==e_y) { r_ans=s; flag=1; return; }
    for (int i=0;i<4;++i)
    {
        int xx=x+fx[r[w][i]],yy=y+fy[r[w][i]];
        if (xx<=0||yy<=0||xx>n||yy>m) continue;
        if (a[xx][yy]=='#') continue;
        r_DFS(xx,yy,r[w][i],s+1);
    }
}
inline void BFS(int s_x,int s_y)
{
    memset(step,0,sizeof(step));
    memset(vis,true,sizeof(vis));
    int head=0,tail=1;
    q[1][0]=s_x; q[1][1]=s_y;  step[s_x][s_y]=1; vis[s_x][s_y]=0;
    while (head<tail)
    {
        int x=q[++head][0],y=q[head][1];
        if (x==e_x&&y==e_y) { min_ans=step[x][y]; return; }
        for (int i=0;i<4;++i)
        {
            int xx=x+fx[i],yy=y+fy[i];
            if (xx<=0||yy<=0||xx>n||yy>m) continue;
            if (a[xx][yy]=='#'||!vis[xx][yy]) continue;
            q[++tail][0]=xx; q[tail][1]=yy; step[xx][yy]=step[x][y]+1; vis[xx][yy]=0;
        }
    }
}
int main()
{
    read(t);
    while (t--)
    {
        read(m); read(n);
        for (i=1;i<=n;++i)
        for (j=1;j<=m;++j)
        {
            cin>>a[i][j];
            if (a[i][j]=='S') s_x=i,s_y=j;
            if (a[i][j]=='E') e_x=i,e_y=j;
        }
        if (s_x==1) w=3; if (s_x==n) w=1; if (s_y==1) w=2; if (s_y==m) w=0;
        flag=0; l_DFS(s_x,s_y,w,1); 
        flag=0; r_DFS(s_x,s_y,w,1); 
        BFS(s_x,s_y);
        printf("%d %d %d\n",l_ans,r_ans,min_ans);
    }
    return 0;
}

 

posted @ 2018-02-12 16:48  空気力学の詩  阅读(238)  评论(0编辑  收藏  举报