【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
题目描述:
话说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搜索解题报告(一)
- 【test】2015.7.28搜索解题报告(二)
- 【test】2015.7.31测试解题报告(一)
- 【test】2015.7.31测试解题报告(二)
- 【test】2015.7.27测试解题报告
- POJ1011 Sticks解题报告(经典搜索)
- POJ 3414 Pots 解题报告(搜索)
- aoj0558解题报告(广度优先搜索)
- NOIP2011 mayan游戏 解题报告(搜索)
- NOIP2015 斗地主 解题报告(搜索)
- TYVJ搜索解题报告
- 搜索专题解题报告
- UOJ147 搜索 解题报告
- 腾迅马拉松(一)解题报告
- 解题报告一
- POJ1013解题报告 暴力搜索
- POJ-1321 棋盘问题 解题报告(搜索) 棋盘问题
- 解题报告-HDOJ-1242(广度优先搜索)
- 【test】2015.7.27测试解题报告
- xpl同学的vfs学习笔记(下)(强烈推荐)
- 【转载】数学游戏(mathgame)解题方法 - N皇后位运算解法,14皇后亦在1秒中
- Linux 2.6内核中新的锁机制--RCU
- 【求解】胜者树做【中位数】
- 【test】2015.7.28搜索解题报告(一)
- 【test】2015.7.28搜索解题报告(二)
- 【test】2015.7.31测试解题报告(一)
- soft lockup
- 【test】2015.7.31测试解题报告(二)
- 【模拟】【程序】2015.8.1noip模拟赛
- 【if版解题】守望者的逃离
- Mips cache lock
- 【题解】8.7夏令营last_test