【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;}
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;}
相关文章推荐
- 【test】2015.7.28搜索解题报告(二)
- codevs 2152 滑雪 搜索 解题报告
- 【在线笔试题解题报告系列】Google APAC 2017 University Test Round E
- hdu 2717 Catch That Cow bfs搜索 解题报告
- NOIP2011 mayan游戏 解题报告(搜索)
- 解题报告:HDU 4090 GemAnd Prince 搜索
- 解题报告 noi 2005 智慧珠游戏(BT 搜索)
- hdu 2102 A计划 bfs搜索 解题报告
- codevs 1225 八数码难题 搜索+Hash 解题报告
- [2011noip day2]7.27test解题报告
- poj 1010 STAMPS 解题报告 -- 搜索 遍历 剪枝
- 搜索专题解题报告
- POJ1011 Sticks解题报告(经典搜索)
- hdu 4751 Divide Groups bfs 搜索 解题报告
- Google APAC 2016 University Graduates Test Round D解题报告
- 【test】2015.7.31测试解题报告(一)
- pku 1308 Is A Tree 搜索 解题报告
- 状态压缩的搜索 Tianjin University 2010 ACM-ICPC Team Sellect Contest 2 1008解题报告
- 搜索题目推荐及解题报告
- 【test】2015.7.31测试解题报告(二)