[kuangbin带你飞]专题一 简单搜索

专题链接:https://cn.vjudge.net/contest/65959

 

A - 棋盘问题

题意:在棋盘上放k个棋子的方案数。要求每行每列至多只有一个。

思路:DFS。详见代码。

#include <cstdio>
using namespace std;
char m[10][10];
int n,k;
int ans;
void dfs(int x,int y,int num)
{
    if(num==k)
    {
        ans++;
        return;
    }
    while(x<=n)
    {
        if(m[x][y]=='#')
        {
            int flag=1;
            for(int j=1;j<=n;j++)
                if(m[j][y]=='*'||m[x][j]=='*') flag=0;
            if(flag==1)
            {
                m[x][y]='*';
                dfs(x,y,num+1);
                m[x][y]='#';
            }
        }
        y++;
        if(y>n)
        {
            y=1;
            x++;
        }
    }

}
int main()
{
    while(~scanf("%d%d",&n,&k))
    {
        if(n==-1&&k==-1) break;
        for(int i=1;i<=n;i++)
            scanf("%s",m[i]+1);
        ans=0;
        dfs(1,1,0);
        printf("%d\n",ans);
    }


    return 0;
}

 

B - Dungeon Master

题意:三维走迷宫问题。

思路:BFS,注意边界判断,详见代码。

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
using namespace std;
const int INF=0x3f3f3f3f;
char m[40][40][40];
bool use[40][40][40];
int dirx[6]={0,0,0,0,1,-1};
int diry[6]={0,0,1,-1,0,0};
int dirz[6]={1,-1,0,0,0,0};
int l,r,c,ans;
struct node
{
    int x;//r
    int y;//c
    int z;//l
    int num;
}s,t;
void bfs()
{
    queue<node >q;
    q.push(s);
    while(!q.empty())
    {
        node now=q.front();
        q.pop();
        use[now.x][now.y][now.z]=1;
        if(now.x==t.x&&now.y==t.y&&now.z==t.z)
            ans=min(ans,now.num);
        else
            for(int i=0;i<6;i++)
            {
                if(now.x+dirx[i]<1||now.x+dirx[i]>r) continue;
                if(now.y+diry[i]<1||now.y+diry[i]>c) continue;
                if(now.z+dirz[i]<1||now.z+dirz[i]>l) continue;
                node next;
                next.x=now.x+dirx[i];
                next.y=now.y+diry[i];
                next.z=now.z+dirz[i];
                next.num=now.num+1;
                if(m[next.x][next.y][next.z]!='#'&&use[next.x][next.y][next.z]==0)
                {
                    q.push(next);
                    use[next.x][next.y][next.z]=1;

                }
            }
    }

}
int main()
{
    while(scanf("%d%d%d",&l,&r,&c)!=EOF)
    {
        if(l==0&&r==0&&c==0) break;
        for(int i=1;i<=l;i++)
        {
            for(int j=1;j<=r;j++)
            {
                getchar();
                for(int k=1;k<=c;k++)
                {
                    scanf("%c",&m[j][k][i]);
                    if(m[j][k][i]=='S')
                        s.x=j,s.y=k,s.z=i,s.num=0;
                    else if(m[j][k][i]=='E')
                        t.x=j,t.y=k,t.z=i;
                }
            }
            getchar();
        }
        memset(use,0,sizeof(use));
        ans=INF;
        bfs();
        if(ans==INF) printf("Trapped!\n");
        else printf("Escaped in %d minute(s).\n",ans);

    }


    return 0;
}B

 

C - Catch That Cow

题意:一维数轴上从n点到k的最短用时。三种移动操作:n+1,n-1,n*2.

思路:BFS问题,从起点开始三个方向进行搜索,注意边界判断,具体看代码。

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int INF=0x3f3f3f3f;
int use[200100];
struct node
{
    int x;
    int num;
};
int ans;
int n,k;
int bfs(int nows)
{
    use[nows]=1;
    queue<node>q;
    while(!q.empty()) q.pop();
    node s;
    s.x=nows,s.num=0;
    q.push(s);
    while(!q.empty())
    {
        node now=q.front();
        q.pop();
        if(now.x==k) return now.num;
        if(now.x+1<=100000&&use[now.x+1]==0)
        {
            use[now.x+1]=1;
            node next;
            next.num=now.num+1;
            next.x=now.x+1;
            q.push(next);
        }
        if(now.x-1>=0&&now.x-1<=100000&&use[now.x-1]==0)
        {
            use[now.x-1]=1;
            node next;
            next.num=now.num+1;
            next.x=now.x-1;
            q.push(next);
        }
        if(now.x*2>=0&&now.x*2<=100000&&use[now.x*2]==0)
        {
            use[now.x*2]=1;
            node next;
            next.num = now.num + 1;
            next.x = now.x * 2;
            q.push(next);
        }
    }
}
int main()
{
    while(~scanf("%d%d",&n,&k))
    {
        memset(use,0,sizeof(use));
        ans=bfs(n);
        printf("%d\n",ans);
    }
    return 0;
}

 

D - Fliptile

题意:一个M×N的棋盘,0表示白色,1表示黑色,每次翻转一个棋子及其相邻的棋子。问能否将棋盘翻转为全白。如果可以输出翻转矩阵。

思路:枚举第一行的翻转情况。因为N<=15。最多有2^15次种情况。对每种情况进行搜索,先翻转第一行棋子,然后遍历第二行开始的所有棋子,当前棋子上面的棋子若为黑,则必须翻转当前棋子。

最后判断最后一行是否全白。记录翻转最小次数。具体看代码。

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
const int INF=0x3f3f3f3f;
int m,n;
int dirx[4]={0,0,-1,1};
int diry[4]={1,-1,0,0};
int mp[20][20];
int lsmp[20][20];
int ans[20][20];
int lsans[20][20];
int num,lsnum;
void f(int x,int y) {
    lsans[x][y]=1;
    lsmp[x][y]=1-lsmp[x][y];
    for(int i=0;i<4;i++)
        if(x+dirx[i]>=1&&x+dirx[i]<=m&&y+diry[i]>=1&&y+diry[i]<=n)
            lsmp[x+dirx[i]][y+diry[i]]=1-lsmp[x+dirx[i]][y+diry[i]];
}
void dfs() {
    lsnum=0;
    for(int i=1;i<=n;i++)
        if(lsans[1][i]==1) {
            f(1,i);
            lsnum++;
        }
    for(int i=2;i<=m;i++)
        for(int j=1;j<=n;j++)
            if(lsmp[i-1][j]==1) {
                f(i,j);
                lsnum++;
            }
    int flag=1;
        for(int j=1;j<=n;j++)
            if(lsmp[m][j]==1) flag=0;
    if(flag==1) {
        if(lsnum<num) {
            num=lsnum;
            for(int i=1;i<=m;i++)
                for(int j=1;j<=n;j++)
                    ans[i][j]=lsans[i][j];
        }
    }
}
int main()
{
    while(cin>>m>>n) {
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
                scanf("%d",&mp[i][j]);
        num=INF;
        for(int k=0;k<(1<<(n));k++)
        {
            memset(lsans,0, sizeof(lsans));
            for(int i=1;i<=m;i++)
                for(int j=1;j<=n;j++)
                    lsmp[i][j]=mp[i][j];
            for(int j=1;j<=n;j++) {
                if(k&(1<<(j-1)))
                    lsans[1][j]=1;
            }

            dfs();
        }
        if(num==INF) printf("IMPOSSIBLE\n");
        else
        {
            
            for (int i = 1; i <= m; i++) {
                for (int j = 1; j <= n; j++)
                    if (j != n) printf("%d ", ans[i][j]);
                    else printf("%d\n", ans[i][j]);

            }
        }
    }
}

 

 E - Find The Multiple

题意:中文题,不多说。

思路:首先注意到所有m肯定是一个小的m×10或者m×10+1得到的。那么我们可以从n开始枚举m,直到找到满足要求(m%n==0)的解。实际上最大的m也不会超过long long 。具体看代码。

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
typedef long long int ll;
const int INF=0x3f3f3f3f;
int n;
void bfs()
{
    queue<ll> q;
    q.push(1);
    while(!q.empty())
    {
        ll now=q.front();
        q.pop();
        if(now%n==0)
        {
            cout<<now<<endl;
            return ;
        }
        q.push(now*10);
        q.push(now*10+1);
    }

}
int main()
{
    while(scanf("%d",&n)&&n)
    {
        bfs();
    }
    return 0;
}

 

F - Prime Path

题意:给出四位数的质数n,m。要求每次变换某一位上的数字且每次变换后的数也是质数,求从n到m的最小变换次数。

思路:n和m都只有四位,预处理出质数,直接BFS即可。具体看代码。

 

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
const int INF=0x3f3f3f3f;
bool flag[10010];
bool visit[10010];
int t,n,m;
struct node
{
    int x;
    int step;
};
void init()
{
    flag[0]=flag[1]=1;
    for(int i=2;i<=10000;i++)
        if(flag[i]==0)
        {
            for(int j=i*2;j<=10000;j+=i)
                flag[j]=1;
        }
}
int power(int x,int t)
{
    int ans=1;
    for(int i=1;i<=t;i++)
        ans*=x;
    return ans;
}
void bfs(int n,int m)
{
    memset(visit,0, sizeof(visit));
    node now;
    visit[n]=1;
    now.x=n,now.step=0;
    queue<node>q;
    q.push(now);
    while(!q.empty())
    {
        node temp=q.front();q.pop();
        if(temp.x==m)
        {
            printf("%d\n",temp.step);
            return ;
        }
        int num[5];
        int nowx=temp.x;
        num[4]=nowx%10;nowx/=10;
        num[3]=nowx%10;nowx/=10;
        num[2]=nowx%10;nowx/=10;
        num[1]=nowx%10;nowx/=10;
        for(int i=1;i<=4;i++)
            for(int j=0;j<=9;j++)
            {
                if(i==1&&j==0) continue;
                if(num[i]==j) continue;
                if(i==4&&j==0) continue;
                int nown=temp.x;
                nown=nown-num[i]*power(10,4-i)+j*power(10,4-i);
                if(flag[nown]==0&&visit[nown]==0)
                {
                    visit[nown]=1;
                    node next;
                    next.x=nown;
                    next.step=temp.step+1;
                    q.push(next);
                }



            }

    }
    printf("Impossible\n");
}
int main()
{
    init();
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        if(n==m) cout<<"0"<<endl;
        else bfs(n,m);
    }
}

 

 G - Shuffle'm Up

题意:给出字符串长度C,两个长度为C的字符串a,b 一个长度为2C的字符串c。每次操作依次轮流从b和a取出字符组成新的字符串d。如果d!=c,将d前半部分给a,后半部分给把,问需要几次操作可以得到C。如果不能输出-1。

思路:虽然放在搜索里,其实是个模拟吧。照着做就行了。注意如果操作次数超过了2C就永远不能组成了。具体看代码。

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
const int INF=0x3f3f3f3f;
bool flag[10010];
bool visit[10010];
int T,C;
string a,b,c;
int main()
{
    cin>>T;
    int cases=1;
    while(T--)
    {
        cin>>C;
        cin>>a>>b>>c;
        if(a+b==c) printf("%d 0\n",cases++);
        else
        {
            int num=0;
            int flag=0;
            while(num<=2*C)
            {
                num++;
                string d="";
                for(int i=0;i<C;i++)
                    d=d+b[i]+a[i];
                if(d==c)
                {
                    flag=1;break;
                }
                a="";
                for(int i=0;i<C;i++)
                    a+=d[i];
                b="";
                for(int i=0;i<C;i++)
                    b+=d[C+i];
            }
            if(flag==0) printf("%d -1\n",cases++);
            else printf("%d %d\n",cases++,num);

        }
    }
}

 

H - Pots

题意:有容量为a,b两个容器,问能否通过三种操作(倒满某个容器,倒空某个容器,将一个容器的水倒入另一个容器)得到容量C。输出最小操作数和操作过程或者impossible。

思路:因为a,b<100,直接6方向BFS即可。可以将操作过程在BFS过程同时更新。具体看代码。

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
const int INF=0x3f3f3f3f;
bool use[110][110];
int aa,bb,cc;
struct caozuo
{
    int num;
    int from;
    int to;
};

struct node
{
    int a;
    int b;
    int step;
    vector<caozuo> v;
};
void bfs()
{
    //temlist.assign(list.begin(), list.end());
    node now;
    now.a=0;
    now.b=0;
    memset(use,0, sizeof(use));
    use[0][0]=1;
    now.v.clear();
    now.step=0;
    queue<node >q;
    q.push(now);
    while(!q.empty())
    {
        node temp=q.front();q.pop();
        if(temp.a==cc||temp.b==cc)
        {
            printf("%d\n",temp.step);
            for(int i=0;i<temp.v.size();i++)
            {
                caozuo now=temp.v[i];
                if(now.num==1)
                {
                    if(now.from==1) printf("FILL(1)\n");
                    else printf("FILL(2)\n");
                }
                else  if(now.num==2)
                {
                    if(now.from==1) printf("DROP(1)\n");
                    else printf("DROP(2)\n");
                }
                else if(now.num==3)
                {
                    if(now.from==1) printf("POUR(1,2)\n");
                    else printf("POUR(2,1)\n");
                }
            }
            return ;
        }
        if(temp.a!=aa&&use[aa][temp.b]==0)//a-fill
        {
            use[aa][temp.b]=1;
            node next;
            next.a=aa;
            next.b=temp.b;
            next.step=temp.step+1;
            next.v.assign(temp.v.begin(),temp.v.end());
            caozuo next1;
            next1.num=1;
            next1.from=1;
            next.v.push_back(next1);
            q.push(next);
        }
        if(temp.b!=bb&&use[temp.a][bb]==0)//b-fill
        {
            use[temp.a][bb]=1;
            node next;
            next.a=temp.a;
            next.b=bb;
            next.step=temp.step+1;
            next.v.assign(temp.v.begin(),temp.v.end());
            caozuo next1;
            next1.num=1;
            next1.from=2;
            next.v.push_back(next1);
            q.push(next);
        }
        if(temp.a!=0&&use[0][temp.b]==0)//a-0
        {
            use[0][temp.b]=1;
            node next;
            next.a=0;
            next.b=temp.b;
            next.step=temp.step+1;
            next.v.assign(temp.v.begin(),temp.v.end());
            caozuo next1;
            next1.num=2;
            next1.from=1;
            next.v.push_back(next1);
            q.push(next);
        }
        if(temp.b!=0&&use[temp.a][0]==0)//b-0
        {
            use[temp.a][0]=1;
            node next;
            next.a=temp.a;
            next.b=0;
            next.step=temp.step+1;
            next.v.assign(temp.v.begin(),temp.v.end());
            caozuo next1;
            next1.num=2;
            next1.from=2;
            next.v.push_back(next1);
            q.push(next);
        }

        if(temp.a!=0&&temp.b!=bb)//a-b
        {
            if(temp.a+temp.b<=bb&&use[0][temp.a+temp.b]==0) {
                use[0][temp.a+temp.b] = 1;
                node next;
                next.a = 0;
                next.b = temp.a+temp.b;
                next.step = temp.step + 1;
                next.v.assign(temp.v.begin(), temp.v.end());
                caozuo next1;
                next1.num=3;
                next1.from=1;
                next1.to=2;
                next.v.push_back(next1);
                q.push(next);
            }
            else if(temp.a+temp.b>bb&&use[temp.a+temp.b-bb][bb]==0) {
                use[temp.a+temp.b-bb][bb] = 1;
                node next;
                next.a = temp.a+temp.b-bb;
                next.b = bb;
                next.step = temp.step + 1;
                next.v.assign(temp.v.begin(), temp.v.end());
                caozuo next1;
                next1.num = 3;
                next1.from = 1;
                next1.to=2;
                next.v.push_back(next1);
                q.push(next);
            }
        }
        if(temp.b!=0&&temp.a!=aa)//b-a
        {
            if(temp.a+temp.b<=aa&&use[temp.a+temp.b][0]==0) {
                use[temp.a+temp.b][0] = 1;
                node next;
                next.a = temp.a+temp.b;
                next.b = 0;
                next.step = temp.step + 1;
                next.v.assign(temp.v.begin(), temp.v.end());
                caozuo next1;
                next1.num=3;
                next1.from=2;
                next1.to=1;
                next.v.push_back(next1);
                q.push(next);
            }
            else if(temp.a+temp.b>aa&&use[aa][temp.a+temp.b-aa]==0) {
                use[aa][temp.a+temp.b-aa] = 1;
                node next;
                next.a = aa;
                next.b = temp.a+temp.b-aa;
                next.step = temp.step + 1;
                next.v.assign(temp.v.begin(), temp.v.end());
                caozuo next1;
                next1.num=3;
                next1.from=2;
                next1.to=1;
                next.v.push_back(next1);
                q.push(next);
            }
        }
    }
    printf("impossible\n");

}
int main()
{
    while(cin>>aa>>bb>>cc)
    {
        bfs();
    }
}

 

I - Fire Game(http://acm.fzu.edu.cn/problem.php?pid=2150)

题意:'#'可以燃烧,'.'不可以燃烧。选择两个#点(可以重复)放火,每过一秒可以向四个方向燃烧,问能否全部烧光所有的#,如果可以给出烧光的最少时间。

思路:注意到数据规模很小,我们可以暴力枚举两个#点。初始化到达每个#的时间为INF。做两遍BFS,到达每个#的时间为两遍BFS里短的时间。每一种情况所需的时间为所有#的最长到达时间。最后取所有最长时间的最小值。具体看代码。可以用双向BFS优化为一次BFS。

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
const int INF=0x3f3f3f3f;
int m,n;
int dirx[4]={0,0,-1,1};
int diry[4]={1,-1,0,0};
char mp[15][15];
int lsans[15][15],ans;
struct node
{
    int x;
    int y;
    int step;
};
bool use[15][15];
void  bfs(int xx,int yy)
{

     memset(use,0,sizeof(use));
     queue<node >q;
     node now;
     now.x=xx,now.y=yy,now.step=0;
     use[xx][yy]=1;
     q.push(now);
     while(!q.empty())
     {
         node now=q.front();
         lsans[now.x][now.y]=min( lsans[now.x][now.y],now.step);
         q.pop();
         for(int i=0;i<4;i++)
         {
             node next;
             next.x=now.x+dirx[i];
             next.y=now.y+diry[i];
             next.step=now.step+1;
             if(use[next.x][next.y]==1) continue;
             if(next.x>=1&&next.x<=n&&next.y>=1&&next.y<=m)
                 if(mp[next.x][next.y]=='#')
                 {
                     use[next.x][next.y]=1;
                     q.push(next);
                 }
         }
     }
}
int main()
{
   int t;
   int cas=1;
   scanf("%d",&t);
   while(t--)
   {
       ans=0;
       scanf("%d%d",&n,&m);
       for(int i=1;i<=n;i++)
           scanf("%s",mp[i]+1);
       for(int i=1;i<=n;i++)
           for(int j=1;j<=m;j++)
               if(mp[i][j]=='#') ans=INF;
       for(int i=1;i<=n*m;i++)
       {
           int nx=i/m+1,ny=i%m;
           if(ny==0) nx--,ny=m;
           if(mp[nx][ny]!='#') continue;
           for(int j=i;j<=n*m;j++)
           {
               int nnx=j/m+1,nny=j%m;
               if(nny==0) nnx--,nny=m;
               if(mp[nnx][nny]=='#')
               {
                   memset(lsans,INF,sizeof(lsans));
                   bfs(nx,ny);
                   bfs(nnx,nny);
                   int lsnum=0;
                   for(int k=1;k<=n;k++)
                       for(int p=1;p<=m;p++)
                           if(mp[k][p]=='#')
                               lsnum=max(lsnum,lsans[k][p]);
                   ans=min(ans,lsnum);
               }
           }
       }
       if(ans!=INF) printf("Case %d: %d\n",cas++,ans);
       else printf("Case %d: -1\n",cas++);
   }
}

 

J - Fire!

题意:F的位置是火,J的位置是人。询问人是否可以逃出迷宫,如果可以求逃出迷宫的时间。注意起火点不一定只有一个。

思路:先做一次BFS求出每个点的起火时间,再做一遍BFS判断能否逃出。具体看代码。

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXN=1010;
int n,m;
struct node
{
    char p;
    int  fire;
    int peo;
    int x;
    int y;
}mp[MAXN][MAXN];
int jx,jy,ans;
bool use[1010][1010];
int dirx[4]={0,0,1,-1};
int diry[4]={1,-1,0,0};
void dfs1()
{

    queue<node >q;
    memset(use,0, sizeof(use));
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            if(mp[i][j].p=='F')
            {
                mp[i][j].fire=0;
                q.push(mp[i][j]);
            }
        }
    while(!q.empty())
    {
        node now=q.front();
        q.pop();
        for(int i=0;i<4;i++)
        {
            if(now.x+dirx[i]>=1&&now.x+dirx[i]<=n&&now.y+diry[i]>=1&&now.y+diry[i]<=m)
                if(use[now.x+dirx[i]][now.y+diry[i]]==0)
                    if(mp[now.x+dirx[i]][now.y+diry[i]].p=='.')
                    {
                        use[now.x+dirx[i]][now.y+diry[i]]=1;
                        mp[now.x+dirx[i]][now.y+diry[i]].fire=now.fire+1;
                        q.push(mp[now.x+dirx[i]][now.y+diry[i]]);
                    }
        }
    }

}
void dfs2()
{
    mp[jx][jy].peo=0;
    queue<node >q;
    q.push(mp[jx][jy]);
    memset(use,0, sizeof(use));
    use[jx][jy]=1;
    while(!q.empty())
    {
        node now=q.front();
        q.pop();
        if(now.x==0||now.x==n+1||now.y==0||now.y==m+1)
            ans=min(ans,now.peo);
        for(int i=0;i<4;i++)
        {
            if(now.x+dirx[i]>=0&&now.x+dirx[i]<=n+1&&now.y+diry[i]>=0&&now.y+diry[i]<=m+1)
                if(use[now.x+dirx[i]][now.y+diry[i]]==0)
                    if(now.x+dirx[i]==0||now.x+dirx[i]==n+1||now.y+diry[i]==0||now.y+diry[i]==m+1||mp[now.x+dirx[i]][now.y+diry[i]].p=='.')
                        if(now.x+dirx[i]==0||now.x+dirx[i]==n+1||now.y+diry[i]==0||now.y+diry[i]==m+1||now.peo+1<mp[now.x+dirx[i]][now.y+diry[i]].fire)
                        {
                            use[now.x+dirx[i]][now.y+diry[i]]=1;
                            mp[now.x+dirx[i]][now.y+diry[i]].peo=now.peo+1;
                            q.push(mp[now.x+dirx[i]][now.y+diry[i]]);
                    }
        }
    }

}

int main()
{
   int t;
   int cas=1;
   scanf("%d",&t);
   while(t--) {
       scanf("%d%d",&n,&m);
       for(int i=1;i<=n;i++)
       {
           getchar();
           for(int j=1;j<=m;j++)
           {
               scanf("%c",&mp[i][j].p);
               if(mp[i][j].p=='J')
               {
                   jx=i;
                   jy=j;
               }
           }
       }
       for(int i=0;i<=n+1;i++)
           for(int j=0;j<=m+1;j++)
               mp[i][j].x=i,mp[i][j].y=j,mp[i][j].peo=mp[i][j].fire=INF;
       ans=INF;
       dfs1();
       dfs2();
       if(ans!=INF) cout<<ans<<endl;
       else cout<<"IMPOSSIBLE"<<endl;
   }

}

 

K - 迷宫问题

题意:5×5的地图,0可以走,1不可以走。求从左上角走到有右下角的唯一最短路径。要求输出路径。

思路:BFS。路径可以保存在每一次的状态里。具体看代码。

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
const int INF=0x3f3f3f3f;
int visit[10][10];
int mp[10][10];
int dirx[4]={0,0,1,-1};
int diry[4]={1,-1,0,0};
struct road
{
    int x;
    int y;
};
struct node
{
    int nx;
    int ny;
    vector<road>v;

};
void bfs()
{
    node now;
    road now1;
    now1.x=1,now1.y=1;
    now.v.push_back(now1);
    now.nx=1,now.ny=1;
    memset(visit,0, sizeof(visit));
    visit[1][1]=1;
    queue<node >q;
    q.push(now);
    while(!q.empty())
    {
        node temp=q.front();
        q.pop();
        if(temp.nx==5&&temp.ny==5)
        {
            int num=temp.v.size();
            for(int i=0;i<num;i++)
            {
                printf("(%d, %d)\n",temp.v[i].x-1,temp.v[i].y-1);
            }
            return ;
        }
        for(int i=0;i<4;i++)
        {
            node next;
            next.nx=temp.nx+dirx[i];
            next.ny=temp.ny+diry[i];
            next.v.assign(temp.v.begin(),temp.v.end());
            road next1;
            next1.x=next.nx;
            next1.y=next.ny;
            next.v.push_back(next1);
            if(next.nx>=1&&next.nx<=5&&next.ny>=1&&next.ny<=5)
                if(visit[next.nx][next.ny]==0&&mp[next.nx][next.ny]==0)
                {
                    visit[next.nx][next.ny]=1;
                    q.push(next);
                }
        }
    }


}
int main()
{
    for(int i=1;i<=5;i++)
        for(int j=1;j<=5;j++)
            cin>>mp[i][j];
    bfs();
}

 

L - Oil Deposits

题意:求联通块数,注意斜对角也算联通。

思路:DFS 每次选择'@'点,将与之联通的设为'.',DFS的次数就是联通块数。

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXN=110;
int n,m;
char mp[MAXN][MAXN];
int dirx[8]={1,-1,0,0,1,1,-1,-1};
int diry[8]={0,0,1,-1,1,-1,1,-1};
int ans;
void dfs(int x,int y)
{
      mp[x][y]='*';
      for(int i=0;i<8;i++)
      {
          int nx=x+dirx[i];
          int ny=y+diry[i];
          if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&mp[nx][ny]=='@') dfs(nx,ny);
      }
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        if(n==0&&m==0) break;
        for(int i=1;i<=n;i++)
        {
            scanf("%s",mp[i]+1);
        }
        ans=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(mp[i][j]=='@')
                {
                    ans++;
                    dfs(i,j);
                }
        printf("%d\n",ans);
    }

}

 

M - 非常可乐(HDOJ1495)

题意:给你一瓶容量为S的可乐和两个容量分别为N、M的杯子。询问最少能平分可乐的次数。如果不能输出NO。

思路:可以看成是一个有六个方向的BFS。六个方向:s->n,s->m,n->s,n->m,n->m,m->n 具体看代码。

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
const int INF=0x3f3f3f3f;
int nn,mm,ss;
bool use[110][110];
struct node
{
    int n;
    int m;
    int s;
    int t;
};
int  bfs()
{
     node now;
     now.n=0,now.m=0,now.s=ss,now.t=0;
     memset(use,0,sizeof(use));
     use[0][0]=1;
     queue<node>q;
     q.push(now);
     while(!q.empty())
     {
         node now=q.front();
         q.pop();
         if(now.n==ss/2&&now.s==ss/2) return  now.t;
         if(now.n<nn)//s->n
         {
             int nextn=nn;
             int nextm=now.m;
             int nexts=now.n+now.s-nn;
             if(use[nextn][nextm]==0)
             {
                 use[nextn][nextm]=1;
                 node next;
                 next.m=nextm;
                 next.n=nextn;
                 next.s=nexts;
                 next.t=now.t+1;
                 q.push(next);
             }
         }
         if(now.m<mm)//s->m
         {
             int nextn=now.n;
             int nextm=mm;
             int nexts=now.m+now.s-mm;
             if(use[nextn][nextm]==0)
             {
                 use[nextn][nextm]=1;
                 node next;
                 next.m=nextm;
                 next.n=nextn;
                 next.s=nexts;
                 next.t=now.t+1;
                 q.push(next);
             }
         }
         if(now.n>0)//n->s
         {
             int nextn=0;
             int nextm=now.m;
             int nexts=now.n+now.s;
             if(use[nextn][nextm]==0)
             {
                 use[nextn][nextm]=1;
                 node next;
                 next.m=nextm;
                 next.n=nextn;
                 next.s=nexts;
                 next.t=now.t+1;
                 q.push(next);
             }
         }
         if(now.m>0)//m->s
         {
             int nextn=now.n;
             int nextm=0;
             int nexts=now.m+now.s;
             if(use[nextn][nextm]==0)
             {
                 use[nextn][nextm]=1;
                 node next;
                 next.m=nextm;
                 next.n=nextn;
                 next.s=nexts;
                 next.t=now.t+1;
                 q.push(next);
             }
         }
         if(now.m>0&&now.n<nn)//m->n
         {
             int nextn,nextm,nexts;
             if(now.m+now.n<=nn)
             {
                 nextm=0;
                 nextn=now.m+now.n;
                 nexts=now.s;
             }
             else
             {
                 nextm=now.m+now.n-nn;
                 nextn=nn;
                 nexts=now.s;
             }
             if(use[nextn][nextm]==0)
             {
                 use[nextn][nextm]=1;
                 node next;
                 next.m=nextm;
                 next.n=nextn;
                 next.s=nexts;
                 next.t=now.t+1;
                 q.push(next);
             }
         }
         if(now.n>0&&now.m<mm)//n->m
         {
             int nextn,nextm,nexts;
             if(now.n+now.m<=mm)
             {
                 nextm=now.m+now.n;
                 nextn=0;
                 nexts=now.s;
             }
             else
             {
                 nextm=mm;
                 nextn=now.n+now.m-mm;
                 nexts=now.s;
             }
             if(use[nextn][nextm]==0)
             {
                 use[nextn][nextm]=1;
                 node next;
                 next.m=nextm;
                 next.n=nextn;
                 next.s=nexts;
                 next.t=now.t+1;
                 q.push(next);
             }
         }

     }
     return 0;
}
int main()
{
    while(~scanf("%d%d%d",&ss,&nn,&mm))
    {
        if(nn==0&&mm==0&&ss==0) break;
        if(nn<mm) swap(nn,mm);
        if(ss%2==1)
            printf("NO\n");
        else
        {
            int ans=bfs();
            if(ans==0)  printf("NO\n");
            else printf("%d\n",ans);
        }
    }

}

 

N - Find a way(HDOJ2612)

题意:求两个人到所有KFC的时间和的最小值。

思路:2次BFS求出两个人分别到每个KFC的时间。最后选择和的最小值。具体看代码。

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
const int INF=0x3f3f3f3f;
int n,m;
char mp[210][210];
bool use[210][210];
int ans1[210][210];
int ans2[210][210];
int dirx[4]={0,0,1,-1};
int diry[4]={1,-1,0,0};
struct node
{
    int x;
    int y;
    int t;
};
void   bfs1()
{
    memset(use,0,sizeof(use));
    memset(ans1,INF,sizeof(ans1));
    node now;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(mp[i][j]=='Y')
            {
                now.x=i;
                now.y=j;
                break;
            }
    now.t=0;
    use[now.x][now.y]=1;
    queue<node >q;
    q.push(now);
    while(!q.empty())
    {
        node now=q.front();
        if(mp[now.x][now.y]=='@')
            ans1[now.x][now.y]=now.t;
        q.pop();
        for(int i=0;i<4;i++)
        {
            node next;
            next.x=now.x+dirx[i];
            next.y=now.y+diry[i];
            next.t=now.t+1;
            if(next.x>=1&&next.x<=n&&next.y>=1&&next.y<=m)
                if(mp[next.x][next.y]!='#')
                    if(use[next.x][next.y]==0)
                    {
                        use[next.x][next.y]=1;
                        q.push(next);
                    }
        }
    }

}
void bfs2()
{
    memset(use,0, sizeof(use));
    memset(ans2,INF,sizeof(ans2));
    node now;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(mp[i][j]=='M')
            {
                now.x=i;
                now.y=j;
                break;
            }
    now.t=0;
    use[now.x][now.y]=1;
    queue<node >q;
    q.push(now);
    while(!q.empty())
    {
        node now=q.front();
        if(mp[now.x][now.y]=='@')
            ans2[now.x][now.y]=now.t;
        q.pop();
        for(int i=0;i<4;i++)
        {
            node next;
            next.x=now.x+dirx[i];
            next.y=now.y+diry[i];
            next.t=now.t+1;
            if(next.x>=1&&next.x<=n&&next.y>=1&&next.y<=m)
                if(mp[next.x][next.y]!='#')
                    if(use[next.x][next.y]==0)
                    {
                        use[next.x][next.y]=1;
                        q.push(next);
                    }
        }
    }
}
void solve()
{
    int ans=INF;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(mp[i][j]=='@')
                ans=min(ans,ans1[i][j]+ans2[i][j]);
    printf("%d\n",ans*11);
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1;i<=n;i++)
            scanf("%s",mp[i]+1);
        bfs1();
        bfs2();
        solve();
    }

}

 

 

转载于:https://www.cnblogs.com/zerocentury/p/8870515.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值