文章目录
简单搜索题目:
深度优先搜索 (POJ 2488,POJ 3083,POJ 3009,POJ 1321,POJ 2251)
广度优先搜索(POJ 3278,POJ 1426,POJ 3126,POJ 3087.POJ 3414)
简单搜索技巧和剪枝(POJ 2531,POJ 1416,POJ 2676,POJ 1129)
2488.A Knight’s Journey
#include <cstdio>
#include <cstring>
using namespace std;
const int MAX_N = 27;
//字典序最小的行走方向
const int dx[8] = {
-1, 1, -2, 2, -2, 2, -1, 1};
const int dy[8] = {
-2, -2, -1, -1, 1, 1, 2, 2};
bool visited[MAX_N][MAX_N];
struct Step{
char x, y;
} path[MAX_N];
bool success; //是否成功遍历的标记
int cases, p, q;
void DFS(int x, int y, int num);
int main()
{
scanf("%d", &cases);
for (int c = 1; c <= cases; c++)
{
success = false;
scanf("%d%d", &p, &q);
memset(visited, false, sizeof(visited));
visited[1][1] = true; //起点
DFS(1, 1, 1);
printf("Scenario #%d:\n", c);
if (success)
{
for (int i = 1; i <= p * q; i++)
printf("%c%c", path[i].y, path[i].x);
printf("\n");
}
else
printf("impossible\n");
if (c != cases)
printf("\n"); //注意该题的换行
}
return 0;
}
void DFS(int x, int y, int num)
{
path[num].y = y + 'A' - 1; //int 转为 char
path[num].x = x + '0';
if (num == p * q)
{
success = true;
return;
}
for (int i = 0; i < 8; i++)
{
int nx = x + dx[i];
int ny = y + dy[i];
if (0 < nx && nx <= p && 0 < ny && ny <= q
&& !visited[nx][ny] && !success)
{
visited[nx][ny] = true;
DFS(nx, ny, num+1);
visited[nx][ny] = false; //撤销该步
}
}
}
3083.Children of the Candy Corn
3009.Curling 2.0
#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#define mod 1000000007
#define eps 1e-6
#define ll long long
#define INF 0x3f3f3f3f
#define MEM(x,y) memset(x,y,sizeof(x))
#define Maxn 25
using namespace std;
int h,w;//横纵坐标
int sx,sy,ex,ey;//起点 终点坐标
int ans;
int mp[Maxn][Maxn];
int dt[][2]= {
{
1,0},{
-1,0},{
0,1},{
0,-1}};//4个方向
void dfs(int x,int y,int step) //在(x, y)位置上的步数step
{
if(x==ex&&y==ey)//到达终点
{
if(step<ans)//若有更小值
ans=step;
return;
}
if(step==10||step>=ans)//若超过10步,或超过当前最短步数
return;
for(int i=0; i<4; i++)//四个方向搜索
{
int tx=dt[i][0]+x;
int ty=dt[i][1]+y;
while(tx>=0&&tx<h&&ty>=0&&ty<w&&mp[tx][ty]!=1)//若此方向能走,则走到尽头,直至出场或撞墙
{
if(tx==ex&&ty==ey)//若在过程中到达目标点
{
step++;
if(step<ans)
ans=step;
return;
}
tx+=dt[i][0];
ty+=dt[i][1];
}
if((tx==x+dt[i][0]&&ty==y+dt[i][1])||tx<0||tx>=h||ty<0||ty>=w)//此方向不能走,或出场
continue;
mp[tx][ty]=0;//撞墙
step++;
dfs(tx-dt[i][0],ty-dt[i][1],step);
step--;//回溯
mp[tx][ty]=1;
}
}
int main()
{
while(cin>>w>>h,w+h)
{
ans=11;//初始化
MEM(mp,0);
for(int i=0; i<h; i++)
for(int j=0; j<w; j++)
{
cin>>mp[i][j];
if(mp[i][j]==2)
{
sx=i;
sy=j;
mp[sx][sy]=0;
}
if(mp[i][j]==3)
{
ex=i;
ey=j;
}
}
dfs(sx,sy,0);//搜索
if(ans==11)
cout<<-1<<endl;
else
cout<<ans<<endl;
}
}
1321.棋盘问题
#include<iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
using namespace std;
int visit[20];
char mp[20][20];
int ans;//ans表示方案数
int k;//k表示棋子数目
int n;//n表示棋盘的大小
int DFS(int x,int y)
{
if(y>=k)//判断是否棋子已经用完,如果用完,记录方案数加1,然后直接返回0
{
ans++;
return 0;
}
for(int i=x;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(!visit[j]&&mp[i][j]=='#')//标记数组仅仅标记某一列上是否有棋子,因为每次递归下一列,所以每一列不会有冲突,只需判断这一列上是否有其他棋子
{
visit[j]=true;//如果该位置该列没被标记且为棋盘,那么在这里放上棋子,并标记,
DFS(i+1,y+1);//搜索下一列
visit[j]=false;//还要注意修改标记后递归回来要及时复原
}
}
}
return 0;
}
int main()
{
while(cin>>n>>k)
{
if(n==-1&&k==-1)
break;
memset(visit,false,sizeof(visit));
memset(mp,false,sizeof(mp));
for(int i=0;i<n;i++)
cin>>mp[i];
ans=0;
DFS(0,0);
cout<<ans<<endl;
}
return 0;
}
2251.Dungeon Master
#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#define mod 1000000007
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
int sl,sx,sy;
int el,ex,ey;
char mp[35][35][35];//记录地图
int vis[35][35][35];//标记是否走过
int base[6][3] = {
{
-1,0,0},{
1,0,0},{
0,-1,0},{
0,1,0},{
0,0,-1},{
0,0,1} };//六个方向
int l,r,c;
struct node
{
int f,x,y;//位置
int step;//步数
friend bool operator<(node a,node b)//步数小的现出来,即时间少
{
return a.step>b.step;//优先队列,步数小的先访问
}
};
priority_queue<node>q;
/*************************bfs***************************/
void bfs()
{
node p;
p.f=sl;//初始化
p.x=sx;
p.y=sy;
p.step=0;
vis[sl][sx][sy]=1;
q.push(p);
while(!q.empty())
{
node s=q.top();
q.pop();
if(s.f==el&&s.x==ex&&s.y==ey)//满足条件
{
printf("Escaped in %d minute(s).\n",s.step);
return;
}
for(int i=0; i<6; i++)//6种走法
{
int tl=s.f+base[i][0];
int tx=s.x+base[i][1];
int ty=s.y+base[i][2];
if(mp[tl][tx][ty]!='#'&&tl>=0&&tl<l&&tx>=0&&tx<r&&ty>=0&&ty<c&&!vis[tl][tx][ty])//判断是否能走
{
node e;
e.f=tl;
e.x=tx;
e.y=ty;
e.step=s.step+1;
vis[e.f][e.x][e.y]=1;
q.push(e);
}
}
}
cout<<"Trapped!"<<endl;
}
/**********************************主函数*********************************/
int main()
{
while(cin >> l >> r >>c,l+r+c)
{
for(int i=0; i<l; i++)
{
for(int j=0; j<r; j++)
{
cin >> mp[i][j];
for(int k=0; k<c; k++)
{
if(mp[i][j][k]=='S')
{
sl=i;
sx=j;
sy=k;
}
if(mp[i][j][k]=='E')
{
el=i;
ex=j;
ey=k;
}
}
}
}
memset(vis,0,sizeof(vis));//每次都要初始化
bfs();
}
}