【test】2015.7.28搜索解题报告(一)

来源:互联网 发布:淘宝怎么直播呀 编辑:程序博客网 时间:2024/06/14 01:45

这是夏令营的第三天,今天讲的主要是搜索,但解题报告今天才写,是因搜索一些细节处理很需要注意,下面就来看看这次的题目。

 

Tour Guides [Russ Cox, 2006]

给出一个N*N的矩阵(1<= N <= 5),现在从左上角出发,走到右下角。而且,每个格子只能走一次,在矩阵中有‘.’和‘#’,‘.’表示可走,‘#’表示不可以走,问,共有多少种行走方案,保证左上角和左下角的格子一定可走。

PROBLEMNAME: tour

 

INPUT FORMAT:

 

一行:N

下面N 行表示一个N*N 的矩阵

SAMPLE INPUT (file tour.in):

 

4

....

#...

#...

....

 

OUTPUT FORMAT:

 

输出可走的方案数

 

SAMPLE OUTPUT (file tour.out):

 

4

 

OUTPUT DETAILS:

下面是可走的方案

   

    abcd     abgh      abef      abcd

    #kje     #cfi      #cdg      #gfe

    #lif     #dej      #lkh      #hij

    nmhg     nmlk      nmji      nmlk

 

【题目分析】

这题就是求路径总数,典型的一道搜索题。但通过样例我们可以看到:虽然题目没有说,但实际上每个可走的点都是要走的,要加一个点记录已走多少格。这样的话用宽度搜索是显然不行的,只能考虑深度搜索,而且数据不大,还是很容易编的。

 

【例程】

#include<cstring>

#include<iostream>

#include<cstdio>

using namespace std;

 

int n,ans=0,sum=0;

int dx[4]={0,0,1,-1};

int dy[4]={1,-1,0,0};

bool num[10][10];

void dfs(int x,int y,int k)

{

       if (!num[x][y])

              return ;

        if(k==sum && y==1 && x==n)  {ans++; return;}

       num[x][y]=0;

       for (int i=0; i<4; i++)

        dfs(x+dx[i],y+dy[i],k+1);

       num[x][y]=1;

}

int main()

{

       freopen("tour.in","r",stdin);  

    freopen("tour.out","w",stdout);

      

       cin>>n;

       memset(num,false,sizeof(num));

       for (int i=1; i<=n; i++)

        for (int j=1; j<=n; j++)

         {

              char ch;

              cin>>ch;

              if (ch=='.')

                      {

                           num[i][j]=true;

                             sum++;

                      }   

                      else num[i][j]=false;

         }

       dfs(1,1,1);

       cout<<ans<<endl;

       return 0;

}




最后的战犯

maze.pas/c/cpp

时限:1s  

题目描述:

话说LuckyFeli3721部队为诱饵,歼灭了大批日军。但顽固的日军军官小犬蠢一狼(以下简称小犬)在全军覆灭之后仍然不肯认输。他躲在山区的一个岩洞中,等待日军的救援部队。他妄图凭借复杂的地形躲避我军的追踪。于是,总部派出足智多谋的Feli前往岩洞搜寻小犬。

Feli来到岩洞入口,发现岩洞其实是一个巨大的迷宫。迷宫地形极为复杂,为一个正方形,其中布满了障碍物。迷宫可以分为N*N2N100)个区域,每个区域或者是空地,或者是不可逾越的障碍物。小犬就躲藏在其中某一个区域内。由于小犬已经忍受了几天的饥饿,Feli进入迷宫时他已经失去思维处于迷乱状态。小犬每秒钟只会沿着他的方向直线前进,如果遇到障碍物或者迷宫边界,他会立刻向右转90度(不会花去时间),继续沿直线前进(初始方向向北)。Feli每秒钟可以自主决定往哪个方向走。如果同一时刻Feli与小犬位于同一个区域,或者相邻的区域(非对角线相邻),Feli可以立刻将小犬抓住。

Feli本来打算先确定小犬的位置,然后沿最短路线抓住他,但是Feli前进时小犬同时也在移动,就不能采取这种方法了。请你帮助Feli确定一种方案,使Feli抓获小犬所用的时间最短

数据说明:

输入数据第一行是一个整数N。以下N行每行N个字符,“*”表示岩洞中的障碍物,“.”表示空地,“J”表示小犬(一开始他会向北走),“F”表示Feli。上北下南左西右东。

 

输出数据仅一行,如果Feli能抓到小犬,那么输出所需的最短时间,如果Feli抓不到小犬,那么这个最后的日本战犯将在岩洞中饿死(因为Feli将在离开的时候封闭岩洞的所有出口),此时输出“No solution.”,不要输出引号。

样例输入(maze.in)

3

F*J

.*.

...

样例输出(maze.out)

3

 

 

【题目分析】

恩,这道题十分逗比,据我所知其数据也十分逗……

不说这个,一般来说解法有两种,一种是用宽度搜索把Feli到所有点的最短路径先标记好,预操作(打表)。然后模拟小犬的走法并检查。第二种就是同时模拟两个人的走法。

虽然两个都可以,但第二种往往会把问题复杂化,所以在能分部份解决问题时最好就分开吧。

 

【例程1,先宽搜法】

#include<iostream>

#include<cstdio>

#include<cstring>

using namespace std;

 

int n;

char num[102][102];

int  a[5]={-1,0,1,0},b[5]={0,1,0,-1};

int xx=0,yy=0,ll=0,ans=0,ge=0;

int jlx,jly,jx,jy;

bool pan=false;

int fang=0;

 

struct lj

{

      int x,y,l;

};

lj d[100001];

 

struct T

{

       int cd;

};

T k[102][102];

 

 

bool check(int u,int ux,int uy)

{

       if(u==k[ux][uy].cd)

              return true;

       for(int i=0;i<4;++i)

       {

              if(u==k[ux+a[i]][uy+b[i]].cd)

                     return true;

       }

       return false;

}

 

void walk()

{

       bool pp=true;

       for(int i=0;i<4;++i)

       {

              if(k[jlx+a[fang]][jly+b[fang]].cd>0)

              {

                     jlx+=a[fang];

                     jly+=b[fang];

                     break;

              }

              else

              {

                     ++fang; 

                     if(fang==4)    fang=0;

              }

       }

}

 

int main()

{

       freopen("maze.in","r",stdin);

       freopen("maze.out","w",stdout);

      

       cin>>n;

    memset(num,'*',sizeof(num));

    memset(k,-1,sizeof(k));

    for(int i=1;i<=n;++i)

    for(int j=1;j<=n;++j)

       {

          cin>>num[i][j];

          if(num[i][j]=='.')

                     ++ge;

              if(num[i][j]=='J')

              {

                     jlx=i;

                     jly=j;

              }

              if(num[i][j]=='F')

              {

                     jx=i;

                     jy=j;

              }

       }

             

       int H=0,T=0;

       d[0].x=jx; 

       d[0].y=jy;

       d[0].l=0;

 

    while(H<=T)

    {

              xx=d[H].x;

        yy=d[H].y; 

              ll=d[H].l; 

             

              if(k[xx][yy].cd==-1)

                     k[xx][yy].cd=ll;

             

        for(int i=0;i<4;++i) 

        {

             if(num[xx+a[i]][yy+b[i]]=='.')

            {

                ++T; 

                d[T].x=xx+a[i];d[T].y=yy+b[i];

                d[T].l=ll+1;

                num[d[T].x][d[T].y]='*';

            }

            if(num[xx+a[i]][yy+b[i]]=='J')

            {

                ++T; 

                d[T].x=xx+a[i];d[T].y=yy+b[i];

                d[T].l=ll+1;

                pan=true;

            }

          }

        ++H; 

      }

      if(!pan)

      {

             cout<<"No solution."<<endl;

             return 0;

      }    

 //Feli所能走的路线

    

     int dog=0;

 

       

    while(true)

    {

              if(check(dog,jlx,jly))

              {    

                     cout<<dog<<endl;

                     return 0;

              }

              walk();

              dog++;

    }

 

}




【例程2,同时走

#include<iostream>

#include<cstdio>

#include<cmath>

#include<cstdlib>

using namespace std;

int n,nl,num;

char m[101][101];

int x2[4]={-1,0,1,0},y2[4]={0,1,0,-1};

struct bfs

{

       int x;

       int y;

       int l;

};

bfs d[100001],f[100001];

int main()

{

       freopen("maze.in","r",stdin);

       freopen("maze.out","w",stdout);

       int w=0,ans=0;

       cin>>n;

       for(int i=0;i<=n+1;i++)

    for(int j=0;j<=n+1;j++)

    {

          m[i][j]='*';

    }

    for(int i=1;i<=n;i++)

    {

    for(int j=1;j<=n;j++)

    {

          cin>>m[i][j];

          if(m[i][j]=='F')

          {

           d[1].x=i;

         d[1].y=j;   

         m[i][j]='.';

          }

          if(m[i][j]=='J')

          {

                 f[1].x=i;

                 f[1].y=j;

                 m[i][j]='.';

          }

    }

    }

    d[1].l=1;

    f[1].l=1;

    int x1=0,y1=0;

    int head=0;

    int tail=1;

    int nl=1;

    int nu=0;

          if(abs(f[d[tail].l].x-d[tail].x)+abs(f[d[tail].l].y-d[tail].y)<=1)

                            {

                            cout<<d[tail].l-1<<endl;

                            exit(0);                              

                            }

    while(head<=tail)

    {

          head++;

          if(nl==d[head].l)       

          {

                 nu=0;

                 while(m[f[nl].x+x2[num]][f[nl].y+y2[num]]!='.')

                 {

                        nu++;

                        num++;

                        if(num==4)

                        num=0;

                        if(nu>4)

                        {

                      cout<<"No solution."; 

                              exit(0);                          

                        }

              }

              nl++;

              f[nl].x=f[nl-1].x+x2[num];

              f[nl].y=f[nl-1].y+y2[num];   

          }

   for(int i=0;i<4;i++)

          {

                 if(m[d[head].x+x2[i]][d[head].y+y2[i]]=='.')

                 {

                        tail++;          

                        d[tail].x=d[head].x+x2[i];

                        d[tail].y=d[head].y+y2[i];

                            d[tail].l=d[head].l+1;

                         m[d[tail].x][d[tail].y]='*';

                            if(abs(f[d[tail].l].x-d[tail].x)+abs(f[d[tail].l].y-d[tail].y)<=1)

                            {

                            cout<<d[tail].l-1<<endl;

                            exit(0);                              

                            }

                     }

          }

    }

    cout<<"No solution."<<endl;

    return 0;

}

0 0
原创粉丝点击