kuangbin带你飞---简单搜索

A棋盘问题

思路:回溯法递归搜索可行位置

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
char Map[10][10];
int lie[10];
int n, k, ans;
void dfs(int row, int num)
{

    if(num <= 0)
    {
        ans++;
        return ;
    }
    if(row <= 0)return;
    for(int i = 1; i <= n; i++)
    {
        if(lie[i] == 0 && Map[row][i] == '#')
        {
            lie[i] = 1;
            dfs(row - 1, num - 1);
            lie[i] = 0;
        }
    }
    dfs(row - 1, num);
}
int main()
{
    while(~scanf("%d%d",&n,&k))
    {
        if(n == -1)
            return 0;
        memset(lie, 0, sizeof(lie));
        ans = 0;
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
            {
                cin>>Map[i][j];
            }
        dfs(n, k);
       printf("%d\n",ans);
    }
    return 0;
}

B - Dungeon Master

思路:直接BFS

#include
#include
#include
#include
#include
using namespace std;
struct node
{
    int x,y,z;
    int floor;
} cur,next; //不用打印路径两个结构体就好
int ex,ey,ez;
char Map[31][31][31];
int vis[31][31][31];
int dir[6][3]= {{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}};
int ans,L,R,C;
int check(int x,int y,int z)
{
    if(x<1||x>L||y<1||y>R||z<1||z>C||vis[x][y][z]==1||Map[x][y][z]=='#')
        return 1;
    return 0;
}
int BFS(int x,int y,int z)
{
    vis[x][y][z]=1;
    cur.x=x,cur.y=y,cur.z=z;
    cur.floor=0;
    queue s;
    s.push(cur);
    while(!s.empty())
    {
        cur=s.front();
        s.pop();
        if(cur.x==ex&&cur.y==ey&&cur.z==ez)
            return cur.floor;
        for(int i=0; i<6; i++)
        {
            int nx,ny,nz;
            nx=cur.x+dir[i][0];
            ny=cur.y+dir[i][1];
            nz=cur.z+dir[i][2];
            if(check(nx,ny,nz))
                continue;
            next.x=nx;
            next.y=ny;
            next.z=nz;
            next.floor=cur.floor+1;
            s.push(next);
            vis[nx][ny][nz]=1;
        }
    }
    return 0;
}
int main()
{
    int sx,sy,sz;
    while(cin>>L>>R>>C)
    {
        if(L==0&&R==0&&C==0)
            return 0;
        for(int i=1;i<=L;i++)
            for(int j=1;j<=R;j++)
               for(int k=1;k<=C;k++)
               vis[i][j][k]=0;
        for(int i=1; i<=L; i++)
            for(int j=1; j<=R; j++)
                for(int k=1; k<=C; k++)
                {
                    cin>>Map[i][j][k];
                    if(Map[i][j][k]=='S')
                        sx=i,sy=j,sz=k;
                    if(Map[i][j][k]=='E')
                        ex=i,ey=j,ez=k;
                }
        ans=BFS(sx,sy,sz);
        if(ans==0)
            printf("Trapped!\n");
        else
            printf("Escaped in %d minute(s).\n",ans);
    }
    return 0;
}

C - Catch That Cow

思路:BFS注意剪枝

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn=1e6+5;
typedef struct node
{
    int v,floor;
}Node;

int vis[maxn];
void BFS(int N,int K)
{
    memset(vis,0,sizeof(vis));
    Node cur;
    cur.v=N;
    cur.floor=0;
    queue que;
    que.push(cur);
    vis[N]=1;
    while(!que.empty())
    {
        cur=que.front();
        que.pop();

        //cout<
        if(cur.v==K)  {  cout<floor<return;}
        int cnt;
        Node next;
        //剪枝方式  如果当前所在的点大于目标点只需减一即可
        //否则执行-1   +1   *2
        if(cur.v>K)
        {
            cnt=cur.v-1;
            if(!vis[cnt]&&cnt>=0)
            {
               next.v=cnt,next.floor=cur.floor+1;
               que.push(next);
               vis[cnt]=1;
            }
        }
        else
        {
            cnt=cur.v-1;
            if(!vis[cnt])
            {
                next.v=cnt,next.floor=cur.floor+1;
                que.push(next);
                vis[cnt]=1;
            }
            cnt=cur.v+1;
            if(!vis[cnt])
            {
                next.v=cnt,next.floor=cur.floor+1;
                que.push(next);
                vis[cnt]=1;
            }
            cnt=cur.v*2;
            if(!vis[cnt])
            {
               next.v=cnt,next.floor=cur.floor+1;
                que.push(next);
                vis[cnt]=1;
            }
        }
    }
}
int main()
{
    int N,K;
    while(cin>>N>>K)
    {
        BFS(N,K);
    }
    return 0;
}

D - Fliptile

思路:开关问题,思路比较难想到。主要是可以根据上一行的状态确定下一行翻转情况,枚举第一行的发转情况就可以确定第一行的状态,进而确定所有的饭庄情况,最后特判最后一行的状态是否符合要求

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;

int Gra[17][17];
int f[17][17]={};
int ans[17][17]={};
int mmin = 0x1f1ffff;

bool judge(int n, int m)
{
    //判断最后一行是否全为0
    for(int i = 1; i <= m; i++)
    {
        if((Gra[n][i] + f[n][i]+ f[n][i - 1] + f[n][i + 1]+ f[n - 1][i]) & 1)
            //通过反转最后一行出现1
            return false;
    }
    return true;
}

void fun(int n, int m, int k, int num)
{
    //从第二行开始  根据枚举的第一行的翻转情况判断是否能够达到目标:最后一行全是0
//用递归的方式实现每一行的更新
//递归过程中  更新f[k][i]数组使得Gra[k-1][i]=0
    if(num > mmin)  return; //剪枝
    if(k > n)
    {
        if(judge(n, m)&&mmin>num)
        {
            memcpy(ans, f, sizeof(f));    //特判最后一行是否达到目标
            mmin = num;
        }
        return;
    }
    int c = 0; //记录翻转次数
    for(int i = 1; i <= m; i++)
    {
        if((Gra[k - 1][i] + f[k - 2][i] + f[k - 1][i - 1] + f[k - 1][i + 1] + f[k - 1][i]) & 1)
        {
            //如果更新过后的Gra[k-1][i]==1  那么就需要进行翻转
            f[k][i] = 1;
            c++;
        }
        else
            f[k][i] = 0;
    }
    fun(n, m, k + 1, num + c); //更新下一行
}

void dfs(int n, int m, int k, int num)
{
    //回溯法枚举第一行的翻转情况
    if(k > m)
    {
        fun(n, m, 2, num);
        return;
    }
    f[1][k] = 0;     //不翻转
    dfs(n, m, k + 1, num);
    f[1][k] = 1;    //翻转
    dfs(n, m, k + 1, num + 1);
}
int main()
{
    int n, m;
    cin >> n >> m;
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
            cin >> Gra[i][j];
    dfs(n, m, 1, 0);
    if(mmin == 0x1f1ffff)
        cout << "IMPOSSIBLE" << endl;
    else
    {
        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= m; j++)
                cout << ans[i][j] << ' ';
            cout << endl;
        }
    }
    return 0;
}

E - Find The Multiple

思路:DFS在深度达到19时return。BFS会超时…

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef long long ll;
#define INF (1<<31)-1
using namespace std;
 int n;
 int flag=1;
void dfs(ll cur,int deep)
{
    if(cur%n==0&&flag)
    {
        cout<0;
        return ;
    }
    if(deep==19)  return;
    if(flag)
    {
        dfs(cur*10,deep+1);
        dfs(cur*10+1,deep+1);
    }
}
int main()
{

    while(cin>>n&&n)
        {
            flag=1;
        dfs(1,1);
    }
    return 0;
}

F - Prime Path

思路:明显的BFS。先素数打表,要求每次只能改变一位数字,每次数字变化时先判断是否是只改变一位数字。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef long long ll;
#define INF (1<<31)-1
using namespace std;

const int maxn = 1e6;
int is_prime[maxn];//存储素数
int vis[maxn];
void Is_prime()
{
    //素数打表
    int n = 10000;
    for(int i = 0; i <= n; i++)
        is_prime[i] = 1;
    is_prime[0] = is_prime[1] = 0;
    for(int i = 2; i <= n; i++)
    {
        if(is_prime[i])
        {
            for(int j = 2 * i; j <= n; j += i)
                if(is_prime[j])  is_prime[j] = 0;
        }
    }
}
struct node
{
    int v, floor;
};
const int dir[8] = {1, -1, 10, -10, 100, -100, 1000, -1000};
int check(int a,int b)
{
    int co=0;
    while(a!=0)
    {
        int x=a%10;
        int y=b%10;
        a/=10;
        b/=10;
        if(x!=y)
            co++;
    }
    if(co!=1) return 0;
    return 1;
}
void BFS(int s, int e)
{
    struct node now, next;
    queueque;
    now.v = s;
    now.floor = 0;
    vis[s] = 1;
    que.push(now);
    while(!que.empty())
    {

        now = que.front();
        que.pop();
        if(now.v == e)
        {
            cout << now.floor << endl;
            return;
        }
        for(int i=0;i<8;i++)
        {
            int cur=now.v;
            for(int j=1;j<10;j++)
            {
                cur+=dir[i];
                if(!check(now.v,cur))  continue;//改变位数超过1位
                if(vis[cur])  continue;//
                 vis[cur]=1;
                if(!is_prime[cur])  continue;//不是素数
                if(cur<1000||cur>9999)  continue;
               // cout<
                next.v=cur;
                next.floor=now.floor+1;
                que.push(next);
            }
        }
    }
    cout<<"Impossible"<int main()
{
    int T;
    cin >> T;
    Is_prime();//先打表
    while(T--)
    {
        memset(vis, 0, sizeof(vis));
        int s, e;
        cin >> s >> e;
        BFS(s, e);
    }
    return 0;
}

G - Shuffle’m Up

思路:模拟问题,都不算搜索。可以用字符数组。用string时注意string支持‘+’操作。赋值操作会出现一下问题:如果string本身长度只有5,你赋值str【5】=‘A’会失败此时需要str+=‘A’。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef long long ll;
#define INF (1<<31)-1
using namespace std;
int main()
{
    int N;
    cin>>N;
    for(int i=1;i<=N;i++)
    {

        int n;
        cin>>n;
        string s1,s2,fin;
        string r1,r2;
        cin>>s1>>s2>>fin;
        cout<' ';
        //cout<
        r1=s1;r2=s2;
        int ans=0;
        while(1)
        {
            string cur;
            ans++;
            for(int j=0;jif(cur==fin)
            {
                    cout<break;
            }
            for(int j=0;j//cout<<"s1:"<

            if(r1==s1&&r2==s2)
            {
                cout<<-1<break;
            }
        }
    }
    return 0;
}


H - Pots

思路:BFS要点是杯子体积的状态改变函数act。非常可乐这一题也用到了这个方式

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef long long ll;
#define INF (1<<31)-1
using namespace std;
int A,B,C;
int vis[105][105]={};
struct node
{
    int a,b;
    int flag;
    int step;
    int floor;
    node(int a=0,int b=0,int flag=-1,int step=-1,int floor=0):a(a),b(b),flag(flag),step(step),floor(floor) {}
}ary[50005];
int act(int& x,int& y,int flag)
{//根据flag的值改变x,y的状态
     if(flag==0)//FILL(1)
     {
         if(x==A) return 0;
         x=A; return 1;
     }
    else if(flag==1)//FILL(2)
     {
         if(y==B) return 0;
         y=B; return 1;
     }
     else if(flag==2)//DROP(1)
     {
         if(x==0)  return 0;
         x=0; return 1;
     }
     else if(flag==3)//DROP(2)
     {
         if(y==0)  return 0;
         y=0; return 1;
     }
     else if(flag==4)//POUR(1,2)
     {
         if(x==0||y==B) return 0;
         int t=B-y;
         if(t>x){//杯子二的空间大于杯子一的体积
           y+=x;
             x=0;
         }
         else {//杯子二的空间小于杯子一的体积
            x-=t;
            y=B;
         }
         return 1;
     }
     else if(flag==5)//POUR(2,1)
     {
         if(y==0||x==A) return 0;
         int t=A-x;
         if(t>y){//杯子一的空间大于杯子二的体积
           x+=y;
             y=0;
         }
         else {//杯子二的空间小于杯子一的体积
            y-=t;
            x=A;
         }
         return 1;
     }
}
int BFS()
{
    queue<int> que;
    ary[0].a=0;ary[0].b=0;
    que.push(0);
    vis[0][0]=1;
    int co=1;
    while(!que.empty())
    {
        int cur=que.front();
        que.pop();
        if(ary[cur].a==C||ary[cur].b==C) return cur;
        for(int i=0;i<=5;i++)
        {
            int n_a=ary[cur].a,n_b=ary[cur].b;
           if(act(n_a,n_b,i))
            {
                if(!vis[n_a][n_b])
                {
                  vis[n_a][n_b]=1;
                  ary[co].a=n_a;ary[co].b=n_b;
                  ary[co].flag=i;ary[co].step=cur;ary[co].floor=ary[cur].floor+1;
                  que.push(co++);
              }
             //cout<
            }
        }
    }
    return -1;//impossible
}
void print(int cur)
{
    if(cur==-1)
        return;
    print(ary[cur].step);
    if(ary[cur].flag==0)
        cout<<"FILL(1)"<if(ary[cur].flag==1)
        cout<<"FILL(2)"<if(ary[cur].flag==2)
        cout<<"DROP(1)"<if(ary[cur].flag==3)
        cout<<"DROP(2)"<if(ary[cur].flag==4)
        cout<<"POUR(1,2)"<if(ary[cur].flag==5)
        cout<<"POUR(2,1)"<using namespace std;
int main()
{

    cin>>A>>B>>C;
    int step=BFS();
    if(step==-1)  cout<<"impossible";
    else
    {
        cout<floor<return 0;
}

I - Fire!

思路:这道题人和火的位置都会改变,因此先要更新火到达每一位置的最短时间(BFS),在搜索人逃离迷宫路线。
注意这里的火不只一处,因此是多起点的BFS

//思路:先更新火焰走遍整个迷宫的最短时间(BFS),初始火焰不止一处注意
//然后判断是否能逃出去  对于每个空间J到达的时间必须早于火焰到达的时间
#include
#include
#include
#include
#include
typedef long long ll;
#define INF (1<<31)-1
using namespace std;
const int maxn=1005;
int R,C;
char Gra[maxn][maxn];
int vis[maxn][maxn];
int fire[maxn][maxn];//记录火焰到达每一个地方的最小时间
int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};

struct node
{
    int x,y,floor;
    node(int x=0,int y=0,int floor=0):x(x),y(y),floor(floor) {}
}cur,Next;

struct Node
{
    int X,Y;
}F[maxn];//记录火焰的初始位置
int check(int x,int y)
{//越界判断
    if(x<1||x>R||y<1||y>C||Gra[x][y]=='#')
        return 1;
    return 0;
}

void BFS_F(int x,int y)
{//更新空间产生火焰的最小时间
    queueque;
     cur.x=x,cur.y=y;cur.floor=0;
     fire[x][y]=0;
     que.push(cur);
     while(!que.empty())
     {
         cur=que.front();
         que.pop();
         for(int i=0;i<4;i++)
         {
            int nx,ny;
            nx=cur.x+dir[i][0];
            ny=cur.y+dir[i][1];
            if(check(nx,ny)||(fire[nx][ny]<=cur.floor+1))//如果该处已经出现火焰,不用入队
                continue;
             Next.x=nx;
             Next.y=ny;
             Next.floor=cur.floor+1;
             fire[nx][ny]=Next.floor;//记录火势到达该地的时间和深搜的层数一样
             //cout<
             que.push(Next);
         }
     }
}
int check_J(int x,int y,int t)
{
  if(Gra[x][y]=='#'||vis[x][y]||fire[x][y]<=t)//不能出现在火势蔓延到的地方
  {
     // cout<
     // cout<<"Gra"<
        return 1;
    }
   return 0;
}
void BFS_J(int x,int y)
{
    cur.x=x,cur.y=y;
    cur.floor=0;
    queueque;
    que.push(cur);
    vis[x][y]=1;
    while(!que.empty())
    {
        cur=que.front();
        que.pop();
        //cout<
        if(cur.x<1||cur.x>R||cur.y<1||cur.y>C)
            {
                cout<floor;
                return;
          }
        for(int i=0;i<4;i++)
        {
            int nx,ny;
            nx=cur.x+dir[i][0];
            ny=cur.y+dir[i][1];
            //cout<
            if(check_J(nx,ny,cur.floor+1))
                continue;
            Next.x=nx,Next.y=ny,Next.floor=cur.floor+1;
           // cout<
            vis[nx][ny]=1;
            que.push(Next);
        }
    }
    cout<<"IMPOSSIBLE";
}
int main()
{
    //cout<
    int t;cin>>t;
    while(t--)
    {
        int c=0;
        memset(Gra,0,sizeof(Gra));
        memset(vis,0,sizeof(vis));
        memset(F,0,sizeof(F));
        cin>>R>>C;
       for(int i=0;i<=R+1;i++)
        for(int j=0;j<=C+1;j++)
           fire[i][j]=INF;//注意处理地图的边界,不然出不去
       int sx,sy;
       for(int i=1;i<=R;i++)
            for(int j=1;j<=C;j++)
            {
                cin>>Gra[i][j];
                if(Gra[i][j]=='J')
                {
                        sx=i;sy=j;
                }
                  if(Gra[i][j]=='F')
                  {
                     F[c].X=i,F[c++].Y=j;
                  }
            }

        for(int i=0;i//cout<<"*";
           BFS_J(sx,sy);
          cout<//cout<
    }
    return 0;
}


J - 迷宫问题

思路:BFS裸题

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef long long ll;
#define INF (1<<31)-1
using namespace std;
int Gra[6][6];
int vis[6][6];
struct node
{
    int x,y;
    int step;
    node (int x=0,int y=0,int step=-1):x(x),y(y),step(step) {}
}path[10000];
int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};

int BFS()
{
    int co=0;  queue<int>que;
    path[0].x=1,path[0].y=1;
    vis[1][1]=1;
    que.push(0);
    while(!que.empty())
    {
        int cur=que.front();
        que.pop();
        if(path[cur].x==5&&path[cur].y==5)  return cur;
        for(int i=0;i<4;i++)
        {
            int nx=path[cur].x+dir[i][0];
            int ny=path[cur].y+dir[i][1];
            if(nx<1||nx>5||ny<1||ny>5||Gra[nx][ny]==1||vis[nx][ny])  continue;
            path[++co].x=nx,path[co].y=ny,path[co].step=cur,vis[nx][ny]=1;
            que.push(co);
        }
    }
}
void print(int step)
{
    if(path[step].step==-1)  return;
    print(path[step].step);
    cout<<"("<1<<", "<1<<")"<int main()
{
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=5;i++)
        for(int j=1;j<=5;j++)
        cin>>Gra[i][j];
    cout<<"(0, 0)"<return 0;
}

K - Oil Deposits

思路:DFS求连通快数目

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef long long ll;
#define INF (1<<31)-1
using namespace std;
const int maxn=105;
int dir[8][2]= {{1,0},{0,1},{-1,0},{0,-1},{-1,-1},{-1,1},{1,-1},{1,1}};
char Gra[maxn][maxn];
int n,m;

void dfs(int x,int y,int first)
{
    if(x<1||x>n||y<1||y>m||Gra[x][y]=='*') return;
    if(first) Gra[x][y]='*';
    first=1;
    for(int i=0; i<8; i++)
        dfs(x+dir[i][0],y+dir[i][1],first);
}
int main()
{
    while(cin>>n>>m&&(n+m)) {
        //memset(vis,0,sizeof(vis));
        int ans=0;
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m; j++)
                cin>>Gra[i][j];
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m; j++) {
                if(Gra[i][j]=='@') {
                    ans++;
                    dfs(i,j,0);
                }
            }
        cout<return 0;
}

L - 非常可乐

思路:重点是三个杯子的状态变化函数act

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef long long ll;
#define INF (1<<31)-1
using namespace std;
const int maxn=101;
int vis[maxn][maxn][maxn];
struct node
{
    int n,m,s,floor;
};
int N,M,S;
int act(int& n,int& m,int& s,int flag)//根据flag的值改变杯子的状态
{
    if(flag==1)//n->m杯1倒给杯2
    {
        if(n==0||m==M) return 0;
        int t=M-m;
        if(t>=n)
        {
            m+=n;
            n=0;
        }
        else
        {
            m=M;
            n-=t;
        }
    }
    if(flag==2)//m->n杯2倒给杯1
    {
        if(m==0||n==N) return 0;
        int t=N-n;
        if(t>=m)
        {
            n+=m;
            m=0;
        }
        else
        {
            n=N;
            m-=t;
        }
    }
    if(flag==3)//n->s杯1倒给杯3
    {
        if(n==0||s==S) return 0;
        int t=S-s;
        if(t>=n)
        {
            s+=n;
            n=0;
        }
        else
        {
            s=S;
            n-=t;
        }
    }
    if(flag==4)//s->n杯3倒给杯1
    {
        if(s==0||n==N) return 0;
        int t=N-n;
        if(t>=s)
        {
            n+=s;
            s=0;
        }
        else
        {
            n=N;
            s-=t;
        }
    }
    if(flag==5)//m->s杯2倒给杯3
    {
        if(m==0||s==S) return 0;
        int t=S-s;
        if(t>=m)
        {
            s+=m;
            m=0;
        }
        else
        {
            s=S;
            m-=t;
        }
    }
    if(flag==6)//s->m杯3倒给杯2
    {
        if(s==0||m==M) return 0;
        int t=M-m;
        if(t>=s)
        {
            m+=s;
            s=0;
        }
        else
        {
            m=M;
            s-=t;
        }
    }
    return 1;
}
void BFS()
{
    struct node cur,nnext;
    queueque;
    cur.n=0,cur.m=0,cur.s=S,cur.floor=0;
    vis[0][0][0]=1;
    que.push(cur);
    while(!que.empty())
    {
        cur=que.front();
        que.pop();
        if((cur.n+cur.m==S&&(cur.n==cur.m))||(cur.n+cur.s==S&&cur.n==cur.s)||(cur.m+cur.s==S&&cur.m==cur.s)) {cout<floor<return;}
        for(int flag=1;flag<=6;flag++)
        {
            int n=cur.n,m=cur.m,s=cur.s;

            if(act(n,m,s,flag)&&!vis[n][m][s])
            {

                vis[n][m][s]=1;
                nnext.n=n,nnext.m=m,nnext.s=s;
                nnext.floor=cur.floor+1;
                que.push(nnext);
            }
        }
    }
    cout<<"NO"<int main()
{
    while(cin>>S>>N>>M&&(N+M+S))
    {
        memset(vis,0,sizeof(vis));
        BFS();
    }
    return 0;
}

M - Find a way

思路:分别对两个人使用BFS,记录下他们到达每个KFC的时间,最后找到两人都能到达,且花费时间最短的KFC即可。
注意两人的初始位置要认为是一道墙。

//说一下思路,分两次对每一个人进行BFS,遍历所有的KFC,更新每个人到达每个KFC的最短时间
//最后遍历time数组,找到最小的和。
//注意Y,M的出发地不能通过相当于墙,如果一个KFC有一方无法到达,则这个KFC不符合条件,时间和舍去
#include
#include
#include
using namespace std;
const int maxn=205;
char Map[maxn][maxn];
int vis[maxn][maxn];
int flag;
int time[maxn][maxn][2];//记录下到达同一个KFC的时间
struct node
{
    int x,y;
    int floor;//所走过的距离
}cur,Next;
int ex,ey;//KFC坐标
int m,n;//矩阵范围
int ans;//记录最短时间初始化为最大值
int co;//记录KFC的个数
int to[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int check(int x,int y)
{
    if(x<1||x>m||y<1||y>n||Map[x][y]=='#'||vis[x][y]==1)
        return 1;
    return 0;
}

void BFS(int sx,int sy)
{
    int num=1;
    queueq;
    cur.x=sx,cur.y=sy,cur.floor=0;
    q.push(cur);
    vis[sx][sy]=1;
    while(!q.empty())
    {
        cur=q.front();
        q.pop();
        if(Map[cur.x][cur.y]=='@')
            {    co++;
                time[cur.x][cur.y][flag]=cur.floor;//flag=0,是Y的时间,flag=1是M的时间
                 if(co==num)
                    return ;
            }
        for(int i=0;i<4;i++)
        {
            int nx,ny;
            nx=cur.x+to[i][0];
            ny=cur.y+to[i][1];
            if(check(nx,ny))
                continue;
            Next.x=nx,Next.y=ny;
            Next.floor=cur.floor+1;
            vis[nx][ny]=1;
            q.push(Next);
        }
    }
}
int main()
{
   while(cin>>m>>n)
   {
       ans=10000000;
      co=0;
      memset(Map,0,m*n*sizeof(char));
      memset(time,0,sizeof(time));
       int x1,y1,x2,y2;
       for(int i=1;i<=m;i++)
        for(int j=1;j<=n;j++)
        {
            cin>>Map[i][j];
            if(Map[i][j]=='Y')
            {
                x1=i,y1=j;
                continue;
            }
            if(Map[i][j]=='M')
            {
                x2=i,y2=j; continue;
            }
            if(Map[i][j]=='@')
            {
                co++;
            }
        }
          Map[x1][y1]='#';
            Map[x2][y2]='#';
           memset(vis,0,sizeof(vis));//注意每次BFS之前都要重置vis数组
            flag=0; //对Y进行BFS
            BFS(x1,y1);
            memset(vis,0,sizeof(vis));
            flag=1;//对M进行BFS
            BFS(x2,y2);
            for(int i=1;i<=m;i++)
                for(int j=1;j<=n;j++)
               {
                if(Map[i][j]!='@')
                   continue;
                if(time[i][j][0]==0||time[i][j][1]==0)
                    continue;
                ans=min(time[i][j][0]+time[i][j][1],ans);
                }
        cout<11<return 0;
}

你可能感兴趣的:(线段树)