您的位置:首页 > 其它

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

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

 

Tour Guides [Russ Cox, 2006]

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

PROBLEM
NAME: 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  

题目描述:

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

Feli来到岩洞入口,发现岩洞其实是一个巨大的迷宫。迷宫地形极为复杂,为一个正方形,其中布满了障碍物。迷宫可以分为N*N(2≤N≤100)个区域,每个区域或者是空地,或者是不可逾越的障碍物。小犬就躲藏在其中某一个区域内。由于小犬已经忍受了几天的饥饿,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;}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: