kuangbin [简单搜索专题]

A-棋盘问题

[POJ - 1321]


#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <map>
#include <climits>
#include <set>
using namespace std;
int n,k;
char mp[10][10];
int book[10];
int ans;
void dfs(int num, int stp)
{
    if (stp==k)
    {
        ans++;
        return;
    }
    if (num==n)
        return ;
    for (int i = 0; i < n; i++)
    {
        if (!book[i] && mp[num][i]=='#')
        {
            book[i]=1;
            dfs(num+1,stp+1);
            book[i]=0;
        }
    }
    dfs(num+1, stp);
    return;
}
int main(void)
{
    while (scanf("%d %d", &n, &k))
    {
        if (k==n&&n==-1)
            break;
        ans = 0;
        memset(book,0,sizeof(book));
        for (int i = 0; i < n; i++)
        {
            scanf(" %s", mp[i]);
        }
        dfs(0,0);
        printf("%d\n",ans);
    }
    return 0;
}

B - Dungeon Master

[POJ - 2251]

题意:有一个高L长R宽C的迷宫, 问从S走到E的步数,如果走不到就输出“Trapped!”。
思路:六个方向BFS。


#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>

using namespace std;

typedef struct node{
    int x, y, z;
    int stp;
}M;
char mp[35][35][35];
int book[35][35][35];
int nxt[6][3] = {1,0,0, -1,0,0, 0,1,0, 0,-1,0, 0,0,1, 0,0,-1};
int L, R, C;
void bfs(int sx, int sy, int sz)
{
    M a,b;
    queue<M>q;
    a.x = sx;
    a.y = sy;
    a.z = sz;
    a.stp = 0;
    q.push(a);
    while (!q.empty())
    {
        a = q.front();
        q.pop();
        if (mp[a.x][a.y][a.z]=='E')
        {
            printf("Escaped in %d minute(s).\n", a.stp);
            return;
        }
        for (int i = 0; i < 6; i++)
        {
            int nx = a.x+nxt[i][0];
            int ny = a.y+nxt[i][1];
            int nz = a.z+nxt[i][2];
            if (nx<0||ny<0||nz<0 || nx>=L ||ny>=R||nz>=C)
                continue;
            if (!book[nx][ny][nz]&&mp[nx][ny][nz]!='#')
            {
                b.x = nx;
                b.y = ny;
                b.z = nz;
                b.stp = a.stp+1;
                q.push(b);
                book[nx][ny][nz]=1;
            }
        }
    }
    printf("Trapped!\n");
}
int main(void)
{
    while (scanf("%d %d %d", &L, &R, &C))
    {
        if (L+R+C==0)
            break;
        int sx,sy,sz;
        memset(book,0,sizeof(book));
        for (int i = 0; i < L; i++)
        {
            for (int j = 0; j < R; j++)
            {
                scanf(" %s", mp[i][j]);
                for (int k = 0; k < C; k++)
                {
                    if (mp[i][j][k]=='S')
                    {
                        sx=i;
                        sy=j;
                        sz=k;
                        book[sx][sy][sz]=1;
                    }
                }
            }
        }
        //printf("%d %d %d", sx, sy, sz);
        bfs(sx,sy,sz);
    }
    return 0;
}

C - Catch That Cow

POJ - 3278

题意:给一个N一个K,问经过多少步(N++,N–,N*=2)后 N可以变成K。
思路:BFS三种情况,注意判断边界。


#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <queue>
using namespace std;
int book[100000+100];
typedef struct node{
    int x,stp;
}P;
int main(void)
{
    int n,k;
    while (~scanf("%d %d", &n, &k))
    {
        memset(book,0,sizeof(book));
        book[n]=1;
        queue<P>q;
        P p;
        p.x=n;
        p.stp=0;
        q.push(p);
        while (!q.empty())
        {
            p = q.front();
            q.pop();
            if (p.x==k)
            {
                printf("%d\n", p.stp);
                break;
            }
            P pp;
            if ( p.x+1<=k && !book[p.x+1])
            {
                pp.x = p.x+1;
                pp.stp = p.stp+1;
                q.push(pp);
                book[p.x+1]=1;
            }
            if (p.x-1>=0 && !book[p.x-1])
            {
                pp.x = p.x-1;
                pp.stp = p.stp+1;
                q.push(pp);
                book[p.x-1]=1;
            }
            if (p.x<=50000 && !book[p.x*2])
            {
                pp.x = p.x*2;
                pp.stp = p.stp+1;
                q.push(pp);
                book[p.x*2]=1;
            }
        }
    }
    return 0;
}

D - Fliptile

POJ - 3279

题意:给一个M*N的图,要求将图中的1全反转成0, 反转一个格子,会将本身及上下左右全部反转, 如果可以反转,则输出最小步数的反转的图,如果不能则输出“IMPOSSIBLE”。
思路:枚举第一行的所有情况
for (int i = 0; i < 1<<N; i++)
{
memset(book,0,sizeof(book));
for (int j = 0; j < N; j++)
book[0][N-j-1] = i>>j&1;
}

然后从第二行开始,如果i-1个是1,则当前位置必反转。直到循环结束,判断最后一行是不是全为0。并记录最小步数。


#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <queue>
#define inf 0x3f3f3f3f
using namespace std;
int M,N;
int mp[20][20];
int ans[20][20];
int book[20][20];
int nxt[5][2]={1,0,0,1,-1,0,0,-1,0,0};
int stp;
int check(int x, int y)
{
    int p=mp[x][y];
    for (int i = 0; i < 5; i++)
    {
        int nx = x + nxt[i][0];
        int ny = y + nxt[i][1];
        if (nx>=0&&nx<M&&ny>=0&&ny<N)
            p+=book[nx][ny];
    }
    return p&1;
}
int F()
{
    for (int i = 1; i < M; i++)
        for (int j = 0; j < N; j++)
            if (check(i-1,j)!=0)
                book[i][j]=1;
    for (int i = 0; i < N; i++)
        if (check(M-1,i)!=0)
            return inf;
    int num = 0;
    for (int i = 0; i < M; i++)
        for (int j = 0; j < N; j++)
            num+=book[i][j];
    return num;
}
void deal()
{
    stp = inf;
    for (int i = 0; i < 1<<N; i++)
    {
        memset(book,0,sizeof(book));
        for (int j = 0; j < N; j++)
            book[0][N-j-1] = i>>j&1;
        int num = F();
        if (num<stp)
        {
            memcpy(ans,book,sizeof(ans));
            stp = num;
        }
    }
    if (stp == inf)
    {
        printf("IMPOSSIBLE\n");
    }
    else
    {
        for (int i = 0; i < M; i++)
        {
            for (int j = 0; j < N; j++)
                printf("%d%c", ans[i][j], j==N-1?'\n':' ');
        }
    }
    return;
}
int main(void)
{
    while (~scanf("%d %d", &M, &N))
    {
        for(int i = 0; i < M; i++)
            for (int j = 0; j < N; j++)
                scanf("%d", &mp[i][j]);
        deal();
    }
    return 0;
}

E - Find The Multiple

POJ - 1426

题意:求能被n整除的只含0 1 的数字。


#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>

using namespace std;
int n,flag;
void dfs(unsigned __int64 t, int n, int k)
{
    if (flag)
        return;
    if (t%n==0)
    {
        printf("%I64u\n", t);
        flag=1;
        return;
    }
    if (k>=19)
        return;
    dfs(t*10,n,k+1);
    dfs(t*10+1,n,k+1);
}
int main(void)
{
    while (scanf("%d", &n))
    {
        if (n==0)
            break;
        flag=0;
        dfs(1,n,0);
    }
    return 0;
}

F - Prime Path

POJ - 3126

题意:将M变换成N,要求每次只能变一位,并且只能变成素数。
思路:对于每位进行bfs。


#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>

using namespace std;
typedef struct node{
    int x;
    int stp;
}P;

int book[10000];

int change(int x, int a, int b)
{
    int num = 0;
    for (int t = 1000; t > 0; t/=10)
    {
        if (a==0)
        {
            num = num*10+b;
            a--;
            continue;
        }
        num = num*10 + (x/t%10);
        a--;
    }
    return num;
}

bool prim(int x)
{
    if (x<=1)
        return false;
    int q = sqrt(x);
    for (int i = 2; i<=q; i++)
    {
        if (x%i==0)
            return false;
    }
    return true;
}

void bfs(int m, int n)
{
    P p,pp;
    p.x = m;
    p.stp = 0;
    queue<P>q;
    q.push(p);
    while (!q.empty())
    {
        p = q.front();
        q.pop();
        if (p.x==n)
        {
            printf("%d\n", p.stp);
            return;
        }
        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j <= 9; j++)
            {
                if (i==0&&j==0)
                    continue;
                int x = change(p.x,i,j);
                if (prim(x)&&!book[x])
                {
                    pp.x = x;
                    pp.stp = p.stp+1;
                    book[x]=1;
                    q.push(pp);
                }
            }
        }
    }
    return;
}
int main(void)
{
    int T;
    scanf("%d", &T);
    while (T--)
    {
        int m,n;
        memset(book,0,sizeof(book));
        scanf("%d %d", &m, &n);
        book[m]=1;
        bfs(m, n);
    }
    return 0;
}

G - Shuffle’m Up

POJ - 3126

题意:给定三个字符串S1,S2,S3。 每次进行一步 将S1,S2拼接成 S1[0]S2[0]S1[1]S2[1]….。然后将前半段为新的S1,后半段为新的S2。 问经过多少次更新,可以将S1,S2合并成S3。
思路:用map存合并成的S3所需要的步数。bfs遍历所有情况。如果队列为空则不可能。


#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#include <map>
#include <set>
using namespace std;
string s1,s2,S;
map<string, int>mp;
int n;
string F(string s1, string s2)
{
    string SS;
    for (int i = 0; i < n; i++)
    {
        SS+=s2[i];
        SS+=s1[i];
    }
    return SS;
}
string change(string ss, int x, int y)
{
    string s;
    for (int i = x; i < y; i++)
        s+=ss[i];
    return s;
}
int bfs(string s1, string s2)
{
    queue<string>q;
    string SS = F(s1,s2);
    q.push(SS);
    mp[SS] = 1;
    while (!q.empty())
    {
        SS = q.front();
        if (SS == S)
        {
            return mp[SS];
        }
        q.pop();
        string S1, S2;
        S1 = change(SS, 0, n);
        S2 = change(SS, n, 2*n);
        string ss = F(S1,S2);
        if (mp[ss]==0)
        {
            mp[ss] = mp[SS]+1;
            q.push(ss);
        }
    }
    return -1;
}
int main(void)
{
    int T,t=1;
    scanf("%d", &T);
    while (T--)
    {
        mp.clear();
        cin>>n>>s1>>s2>>S;
        int ans = bfs(s1, s2);
        printf("%d %d\n", t++, ans);
    }   
    return 0;
}

H - Pots

POJ - 3414

题意:有两个杯子,有三种操作:
1.FILL(i) 将i杯子接满水。
2.DROP(i) 将i杯子倒空。
3.POUR(i,j) 将i杯子的水倒往j杯子。
问能不能倒出C容量的水,并输出步骤。
思路:模拟队列,分别有6步:

1 ->A 2 ->B 3 A->B 4 B->A 5 A-> 6 B->

进行BFS, 写着比较复杂,但基本都是复制粘贴,注意处理A->B,跟B->A,就好。


#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <map>
#include <set>
#include <queue>
using namespace std;
int A,B,C;
struct node {
    int x,y,rear,stp;
    int flag;  // 1 ->A 2 ->B  3 A->B  4 B->A  5 A->  6 B->
}P[100000+100];
int book[300][300];
void out(int x)
{
    switch(x)
    {
        case 1:{
            printf("FILL(1)\n");
            break;
        }
        case 2:{
            printf("FILL(2)\n");
            break;
        }
        case 3:{
            printf("POUR(1,2)\n");
            break;
        }
        case 4:{
            printf("POUR(2,1)\n");
            break;
        }
        case 5:{
            printf("DROP(1)\n");
            break;
        }
        case 6:{
            printf("DROP(2)\n");
        }
    }
}
void print(int t)
{
    if (P[t].rear==-1)
        return;
    print(P[t].rear);
    out(P[t].flag);
    return;
}
void bfs()
{
    int S=0,E=1;
    P[S].x=0;
    P[S].y=0;
    P[S].stp=0;
    P[S].flag=0;
    P[S].rear=-1;
    book[0][0]=1;
    struct node p;
    while (S<E)
    {
        if (P[S].x==C || P[S].y==C)
        {
            printf("%d\n",P[S].stp);
            print(P[S].rear);
            out(P[S].flag);
            return;
        }
        for (int i = 1; i <= 6; i++)
        {
            P[E].rear = S;
            P[E].stp = P[S].stp+1;
            P[E].flag = i;
            if (i==1&&P[S].x!=A)
            {
                P[E].x = A;
                P[E].y = P[S].y;
            }
            if (i==2&&P[S].y!=B)
            {
                P[E].y = B;
                P[E].x = P[S].x;
            }
            if(i==3&&P[S].x!=0&&P[S].y!=B)
            {
                P[E].y = (P[S].x+P[S].y)>B ? B:(P[S].x+P[S].y);
                P[E].x = (P[S].x+P[S].y)>B ? (P[S].x+P[S].y-B):0;
            }
            if (i==4&&P[S].y!=0&&P[S].x!=A)
            {
                P[E].x = (P[S].x+P[S].y)>A ? A:(P[S].x+P[S].y);
                P[E].y = (P[S].x+P[S].y)>A ? (P[S].x+P[S].y-A):0;
            }
            if (i==5)
            {
                P[E].x=0;
                P[E].y = P[S].y;
            }
            if(i==6)
            {
                P[E].y=0;
                P[E].x = P[S].x;
            }

            if (book[P[E].x][P[E].y]==0)
            {
                book[P[E].x][P[E].y]=1;
                E++;
            }
        }
        S++;
    }
    printf("impossible\n");
    return;
}
int main(void)
{
    while (~scanf("%d %d %d", &A, &B, &C))
    {
        memset(book,0,sizeof(book));
        bfs();
    }
    return 0;
}

I - Fire Game

FZU - 2150

题意:有两个小朋友要在一个平面内的草地上点火, 当一个人点燃一块草地之后,每秒火都会向周围四个方向扩散,每人只能点燃一块,问最少的时间将这个平面内的草地烧干净,输出最短的时间,如果不可能输出-1。
思路:m,n只有10,两两枚举所有的“#”,并进行bfs寻找最少的时间。


#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <queue>
#include <map>
#include <set>
#define inf 0x3f3f3f3f
using namespace  std;
int n,m;
char mp[20][20];
int book[20][20];
int nxt[4][2] = {1,0,0,1,-1,0,0,-1};
typedef struct {
    int x, y;
}Point;
int bfs(int x, int y, int xx, int yy)
{
    memset(book,inf,sizeof(book));
    queue<Point>q;
    Point p,pp;
    p.x = x;
    p.y = y;
    q.push(p);
    p.x = xx;
    p.y = yy;
    q.push(p);
    book[x][y]=0;
    book[xx][yy]=0;
    while (!q.empty())
    {
        p = q.front();
        q.pop();
        for (int i = 0; i < 4; i++)
        {
            pp.x = p.x+nxt[i][0];
            pp.y = p.y+nxt[i][1];
            if (pp.x<0||pp.y<0||pp.x>=n||pp.y>=m)
                continue;
            if (mp[pp.x][pp.y]!='.' && book[pp.x][pp.y]>book[p.x][p.y]+1)
            {
                book[pp.x][pp.y]=book[p.x][p.y]+1;
                q.push(pp);
            }
        }
    }
    int ans = -1;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
        {
            if (mp[i][j]=='#')
            {
                if (book[i][j]==inf)
                    return inf;
                ans = max(book[i][j],ans);
            }
        }
    }
    return ans;
}
int main(void)
{
    int T,t=1;
    scanf("%d", &T);
    while (T--)
    {
        scanf("%d %d", &n, &m);
        for (int i = 0; i < n; i++)
        {
            scanf(" %s", mp[i]);
        }
        int ans = inf;
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                if (mp[i][j]=='#')
                {
                    for (int I = 0; I < n; I++)
                    {
                        for (int J = 0; J < m; J++)
                        {
                            if (mp[I][J]=='#')
                            {
                                int tmp = bfs(i,j,I,J);
                                ans = min(ans, tmp);
                            }
                        }
                    }
                }
            }
        }
        printf("Case %d: %d\n", t++, ans==inf?-1:ans);
    }
    return 0;
}

J - Fire!

UVA - 11624

题意:一个人在迷宫里面,迷宫着火了,火每秒向周围四个方向扩散,人每秒走一步,问人能不能逃出去。
思路:先对整个地图的所有“F”进行BFS,找到地图上所有点被点燃的最短时间,然后再对人进行BFS。
注意:不止有一处着火。


#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#include <map>
#include <set>
#define inf 0x3f3f3f3f
using namespace std;
int m,n;
char mp[1100][1100];
int nxt[4][2]={1,0, 0,1, -1,0, 0,-1};
int book[1100][1100];
void bfs_fire()
{
    memset(book,inf,sizeof(book));
    queue<int>qx,qy;
    for (int i = 0; i < m; i++)
    {
        for (int j = 0; j < n; j++)
        {
            if (mp[i][j] == 'F')
            {
                book[i][j]=0;
                qx.push(i);
                qy.push(j);
            }
        }
    }
    while (!qx.empty())
    {
        int x = qx.front();
        int y = qy.front();
        qx.pop();
        qy.pop();
        for (int i = 0; i < 4; i++)
        {
            int xx = x+nxt[i][0];
            int yy = y+nxt[i][1];
            if (xx<0||yy<0||xx>=m||yy>=n)
                continue;
            if (mp[xx][yy]!='.')
                continue;
            if (book[x][y]+1>=book[xx][yy])
                continue;
            book[xx][yy]=book[x][y]+1;
            qx.push(xx);
            qy.push(yy);
        }
    }
    return;
}
int bfs2(int x, int y)
{
    queue<int>qx,qy;
    qx.push(x);
    qy.push(y);
    book[x][y]=0;
    while (!qx.empty())
    {
        x = qx.front();
        y = qy.front();
        qx.pop();
        qy.pop();
        for (int i = 0; i < 4; i++)
        {
            int xx = x+nxt[i][0];
            int yy = y+nxt[i][1];
            if (mp[xx][yy]!='.')
                continue;
            if (book[x][y]+1 >= book[xx][yy])
                continue;
            if (xx==m-1||yy==n-1||xx==0||yy==0)
                return book[x][y]+2;
            book[xx][yy] = book[x][y]+1;
            qx.push(xx);
            qy.push(yy);
        }
    }
    return -1;
}
int main(void)
{
    int T;
    scanf("%d", &T);
    while (T--)
    {
        scanf("%d %d", &m, &n);
        int jx,jy;
        for (int i = 0; i < m; i++)
        {
            scanf(" %s", mp[i]);
            for (int j = 0; j < n; j++)
            {
                if (mp[i][j]=='J')
                {
                    jx=i;
                    jy=j;
                }
            }
        }
        if (jx==m-1||jy==n-1||jx==0||jy==0)
        {
            printf("1\n");
            continue;
        }
        int ans = -1;
        bfs_fire();
        ans = bfs2(jx,jy);
        if (ans==-1)
            printf("IMPOSSIBLE\n");
        else
            printf("%d\n",ans);
    }
    return 0;
}

K - 迷宫问题

POJ - 3984

题意:中文题。。
思路 : 数组模拟队列,递归回溯输出。


#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
struct node{
    int x,y,s;
}Step[10000+100];
int mp[10][10];
void print(int S)
{
    if (Step[S].x==0 && Step[S].y==0)
        return;
    print(Step[S].s);
    printf("(%d, %d)\n",Step[S].x, Step[S].y);
    return;
}
void bfs(int x, int y)
{
    int nxt[4][2] = {1,0, 0,1, -1,0, 0,-1};
    int S = 0, E=1;
    Step[S].x = x;
    Step[S].y = y;
    Step[S].s = 0;
    while (S<E)
    {
        for (int i = 0; i < 4; i++)
        {
            int nx = Step[S].x+nxt[i][0];
            int ny = Step[S].y+nxt[i][1];
            if (nx<0||ny<0||nx==5||ny==5)
                continue;
            if (mp[nx][ny]==0)
            {
                mp[nx][ny]=1;
                Step[E].x = nx;
                Step[E].y = ny;
                Step[E].s = S;
                E++;
            }
            if (nx==4&&ny==4)
            {
                print(S);
                return;
            }
        }
        S++;
    }
}
int main(void)
{
    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 5; j++)
        {
            scanf("%d", &mp[i][j]);
        }
    }
    mp[0][0]=1;
    printf("(0, 0)\n");
    bfs(0,0);
    printf("(4, 4)\n");
    return 0;
}

L - Oil Deposits

HDU - 1241

题意: 问有多少个连通区域。
思路: 循环,找到“@”就进行dfs,ans++,并标记为“*”;


#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
int m,n;
char mp[120][120];
int nxt[8][2]={1,0, 1,1, 0,1, -1,1, -1,0, -1,-1, 0,-1, 1,-1};
void dfs(int x, int y)
{
    for (int i = 0; i < 8; i++)
    {
        int nx = x + nxt[i][0];
        int ny = y + nxt[i][1];
        if (nx<0||ny<0||nx>=m||ny>=n)
            continue;
        if (mp[nx][ny]=='@')
        {
            mp[nx][ny]='*';
            dfs(nx,ny);
        }
    }
    return;
}
int main(void)
{
    while (scanf("%d %d", &m, &n))
    {
        if (m==0 && n==0)
            break;
        for (int i = 0; i < m; i++)
            scanf(" %s", mp[i]);
        int ans = 0;
        for (int i = 0; i < m; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (mp[i][j]=='@')
                {
                    ans++;
                    mp[i][j]='*';
                    dfs(i,j);
                }
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

M - 非常可乐

HDU - 1495

题意:中文题。
思路:三个瓶子来回倒, 一共六种情况,分别列举BFS。注意处理瓶子满的,或者空着的情况。


#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <queue>
using namespace std;
int S,N,M;
int book[120][120][120];
typedef struct node{
    int x,y,z;
    int stp;
}P;
bool check(P p)
{
    if (p.x==p.y&&p.x==S/2)
        return true;
    if (p.x==p.z&&p.x==S/2)
        return true;
    if (p.z==p.y&&p.y==S/2)
        return true;
    return false;
}
void bfs()
{
    queue<P> q;
    P p,pp;
    p.x = S;
    p.y = 0;
    p.z = 0;
    p.stp = 0;
    book[p.x][p.y][p.z]=1;
    q.push(p);
    while (!q.empty())
    {
        p=q.front();
        q.pop();
        if (check(p))
        {
            printf("%d\n", p.stp);
            return ;
        }
        for (int i = 1; i<=6; i++)
        {
            pp.x = p.x;
            pp.y = p.y;
            pp.z = p.z;
            pp.stp = p.stp+1;
            if (i==1)
            {
                pp.x = (p.x+p.y)>N? (p.x+p.y-N):0;
                pp.y = (p.x+p.y)>N? N:(p.x+p.y);
            }
            if (i==2)
            {
                pp.x = (p.x+p.z)>M? (p.x+p.z-M):0;
                pp.z = (p.x+p.z)>M? M:(p.x+p.z);
            }
            if (i==3)
            {
                pp.x = (p.x+p.y)>S? S:(p.x+p.y);
                pp.y = (p.x+p.y)>S? (p.x+p.y-S):0;
            }
            if (i==4)
            {
                pp.z = (p.y+p.z)>M? M:(p.y+p.z);
                pp.y = (p.z+p.y)>M? (p.z+p.y-M):0;
            }
            if (i==5)
            {
                pp.x = (p.x+p.z)>S? S:(p.x+p.z);
                pp.z = (p.x+p.z)>S? (p.x+p.z-S):0;
            }
            if (i==6)
            {
                pp.y = (p.y+p.z)>N? N:(p.y+p.z);
                pp.z = (p.y+p.z)>N? (p.y+p.z-N):0;
            }
            if (!book[pp.x][pp.y][pp.z])
            {
                book[pp.x][pp.y][pp.z]=1;
                q.push(pp);
            }
        }
    }
    printf("NO\n");
    return ;
}
int main(void)
{
    while (~scanf("%d %d %d", &S, &N, &M))
    {
        if (S==0&&M==0&&N==0)
            break;
        if (S&1)
        {
            printf("NO\n");
            continue;
        }
        memset(book,0,sizeof(book));
        bfs();
    }
    return 0;
}

N - Find a way

HDU - 2612

题意:Y和M要在“@”的地方见面, 地图上有不止一个“@”,两个人每11分钟移动一次,只能向上下左右四个方向移动,问他们两个在“@”处见面的最少时间。
思路:分别BFS求出两个人到达所有“@”的时间,再求最小。


#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
using namespace std;
typedef struct node{
    int x, y, stp;
}P;
int num[300][300];
char mp[300][300];
int book[300][300];
int m,n;
void bfs(int x, int y)
{
    int nxt[4][2] = {0,1, 1,0, -1,0, 0,-1};
    queue<P> q;
    P p, pp;
    p.x = x;
    p.y = y;
    p.stp = 0;
    q.push(p);
    book[x][y]=1;
    while (!q.empty())
    {
        p=q.front();
        q.pop();
        pp.stp = p.stp+1;
        for (int i = 0; i < 4; i++)
        {
            pp.x = p.x+nxt[i][0];
            pp.y = p.y+nxt[i][1];
            if (pp.x<0||pp.y<0||pp.x>=m||pp.y>=n)
                continue;
            if (!book[pp.x][pp.y] && mp[pp.x][pp.y]!='#')
            {
                book[pp.x][pp.y]=1;
                if (mp[pp.x][pp.y]=='@')
                {
                    num[pp.x][pp.y]+=pp.stp;
                }
                q.push(pp);
            }
        }
    }
    return;
}
int main(void)
{
    while (~scanf("%d %d", &m, &n))
    {
        for (int i = 0; i < m; i++)
            scanf(" %s", mp[i]);
        memset(num,0,sizeof(num));
        for (int i = 0; i < m; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (mp[i][j]=='Y')
                {
                    memset(book,0,sizeof(book));
                    bfs(i,j);
                }
                if (mp[i][j]=='M')
                {
                    memset(book,0,sizeof(book));
                    bfs(i,j);
                }
            }
        }
        int Min = 50000;
        for (int i = 0; i < m; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (mp[i][j]=='@' && num[i][j]<Min && num[i][j]>0)
                {
                    Min = num[i][j];
                }
            }
        }
        printf("%d\n", Min*11);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值