快要期末考试来了,最近也没怎么看算法,整理下我前段时间做的搜索超级水题吧,多做点搜索水题也算是为以后学习图论做点准备,baka哥说图论的算法基本都是DFS和BFS。
POJ 1321 棋盘问题
链接:http://poj.org/problem?id=1321
代码:
#include<cstdio>
#include<cstring>
char mapn[9][9];
int visit[9];//记录列数是否相同
int n,k,tot;
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
void DFS(int a,int step)//a表示行号
{
if(step==k)
{
tot++;
return ;
}
if(a>=n)
return ;
for(int i=0;i<n;i++)
{
if(!visit[i]&&mapn[a][i]=='#')
{
visit[i]=1;
DFS(a+1,step+1);
visit[i]=0;
}
}
DFS(a+1,step); //第a+1行不放棋子的情况
}
int main()
{
int i;
while(scanf("%d%d",&n,&k)!=EOF)
{
if(n==-1&&k==-1)
break;
tot=0;
memset(visit,0,sizeof(visit));
for(i=0;i<n;i++)
scanf("%s",mapn[i]);
DFS(0,0);
printf("%d\n",tot);
}
return 0;
}
HDU 1016 Prime RIng Problem
链接:http://acm.hdu.edu.cn/showproblem.php?pid=1016
代码:
#include<cstdio>
#include<cstring>
int n;
int isp[40],visit[21],A[21];
bool is_prime(int m)
{
if(m==2||m==3)
return 1;
for(int i=2;i*i<=m;i++)
if(m%i==0)
return 0;
return 1;
}
void DFS(int cur)
{
if(cur==n&&isp[A[0]+A[cur-1]]) //递归边界
{
for(int i=0;i<n-1;i++)
printf("%d ",A[i]);
printf("%d\n",A[n-1]);
}
else
for(int i=1;i<=n;i++)
{
if(!visit[i]&&isp[i+A[cur-1]])//如果i没有用过,是否和相邻的加起来是素数
{
A[cur]=i;
visit[i]=1;
DFS(cur+1);
visit[i]=0;
}
}
}
int main()
{
for(int i=2;i<=40;i++)
isp[i]=is_prime(i);
int k=1;
while(scanf("%d",&n)!=EOF)
{
printf("Case %d:\n",k);
memset(visit,0,sizeof(visit));
A[0]=1;
k++;
visit[0]=1;
visit[1]=1;
DFS(1);
printf("\n");
}
return 0;
}
HDU 1253胜利大逃亡
链接:http://acm.hdu.edu.cn/showproblem.php?pid=1253
代码:
#include<stdio.h>
#include<queue>
using namespace std ;
int a, b, c, T;
int map[51][51][51] ;
int dir[6][3] ={{1,0,0},{-1,0,0},{0,0,1},{0,0,-1},{0,1,0},{0,-1,0}};
struct node
{
int x,y,z,step;
}start;
void BFS()
{
queue<node> q ;
node cur,next;
start.x=0;
start.y=0;
start.z=0;
start.step=0;
map[0][0][0] = 1 ;
q.push(start) ;
while(!q.empty())
{
cur = q.front() ;
q.pop() ;
for(int i=0; i<6; i++)
{
next.x=cur.x+dir[i][0];
next.y=cur.y+dir[i][1];
next.z=cur.z+dir[i][2];
if(next.x==a-1&&next.y==b-1&&next.z==c-1&&cur.step<=T)
{
printf("%d\n", cur.step+1) ;
return ;
}
if(next.x>=0&&next.x<a&&next.y>=0&&next.y<b&&next.z>=0&&next.z<c&&!map[next.x][next.y][next.z])
{
map[next.x][next.y][next.z] = 1 ;
next.step=cur.step+1;
q.push(next) ;
}
}
}
printf("-1\n") ;
return ;
}
int main()
{
int t ;
scanf("%d", &t) ;
while(t--)
{
scanf("%d%d%d%d", &a, &b, &c, &T) ;
for(int i=0; i<a; i++)
for(int j=0; j<b; j++)
for(int k=0; k<c; k++)
scanf("%d", &map[i][j][k]) ;
if(map[a-1][b-1][c-1]||a+b+c-3>T) //终点在墙上或者距离终点的最短距离大于要求时间
{
printf("-1\n") ;
continue ;
}
if(a==1&&b==1&&c==1)
{
printf("0\n") ;
continue ;
}
BFS() ;
}
return 0 ;
}
HDU 1312 Red and Black
链接:http://acm.hdu.edu.cn/showproblem.php?pid=1312
代码:
#include<cstdio>
#include<queue>
using std::queue;
int n,m;
int dir[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
char map[21][21];
struct point
{
int x,y;
}start;
int num;
int BFS(int a,int b)
{
int i;
queue<point> q;
point cur,next;
start.x=a;
start.y=b;
q.push(start);
num=1;
while(!q.empty())
{
cur=q.front();
q.pop();
for(i=0;i<4;i++)
{
next.x=cur.x+dir[i][0];
next.y=cur.y+dir[i][1];
if(next.x>=0&&next.x<n&&next.y>=0&&next.y<m&&map[next.x][next.y]!='#')
{
num++;
map[next.x][next.y]='#';
q.push(next);
}
}
}
return num;
}
int main()
{
int i,j,si,sj;
while(scanf("%d%d",&m,&n)!=EOF)
{
if(n==0&&m==0)
break;
getchar();
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
scanf("%c",&map[i][j]);
if(map[i][j]=='@')
{
si=i;
sj=j;
}
}
getchar();
}
map[si][sj]='#';
printf("%d\n",BFS(si,sj));
}
return 0;
}
HDU 2553 N皇后问题
链接:http://acm.hdu.edu.cn/showproblem.php?pid=2553
数组记录代码:
#include<cstring>
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<map>
#include<queue>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-8
#define pi acos(-1.0)
using namespace std;
int n,tot;
int vis[3][22];
void dfs(int cur)
{
if(cur==n)
{
tot++;
return ;
}
else
for(int i=0; i<n; i++)
if(!vis[0][i]&&!vis[1][cur+i]&&!vis[2][cur-i+n]) //主对角线加n为保证数组下标不小于0,小白书上有说明
{
vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=1;
dfs(cur+1);
vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=0;
}
}
int main()
{
int result[11];
for(n=0; n<11; n++) //在外边打表,不然会超时
{
memset(vis,0,sizeof(vis));
tot=0;
dfs(0);
result[n]=tot;
}
while(scanf("%d",&n)!=EOF)
{
if(n==0)
break;
printf("%d\n",result[n]);
}
return 0;
}
直接DFS代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int n,ans;
int map[15];
int visit[15];
int sol[15];
void dfs(int k)
{
int i,j,flag;
if(k==n+1)
{
ans++;
return;
}
for(i=1;i<=n;i++)
if(!visit[i]) //各行棋子不能在同一竖
{
map[k]=i;
flag=1;
for(j=1;j<=k-1;j++)
if((abs(map[k]-map[j]))==abs((k-j))) //判断是否在同一斜线上
{
flag=0;
break;
}
if(flag)
{
visit[i]=1;
dfs(k+1);
visit[i]=0; //释放第i列,进行下一次搜索
}
}
}
int main()
{
int i;
for(i=1;i<=10;i++)
{
ans=0;
n=i;
memset(map,0,sizeof(map));
memset(visit,0,sizeof(visit));
dfs(1);
sol[i]=ans;
}
while(scanf("%d",&n),n)
printf("%d\n",sol[n]);
return 0;
}
HDU 1241 Oil Deposits
链接:http://acm.hdu.edu.cn/showproblem.php?pid=1241
这也是一道很水的BFS,只要找出相连的区域块的数目就好。
代码:
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
int n,m;
char map[101][101];
int dir[8][2]={{0,1},{1,1},{1,0},{1,-1},{-1,1},{0,-1},{-1,0},{-1,-1}};
struct point
{
int x,y;
}start;
void BFS(int a,int b)
{
start.x=a;
start.y=b;
queue<point> q;
int i;
point cur,next;
q.push(start);
while(!q.empty())
{
cur=q.front();
q.pop();
for(i=0;i<8;i++)
{
next.x=cur.x+dir[i][0];
next.y=cur.y+dir[i][1];
if(next.x>=0&&next.x<n&&next.y>=0&&next.y<m)
{
if(map[next.x][next.y]=='@')
{
map[next.x][next.y]='*';
q.push(next);
}
}
}
}
}
int main()
{
int i,j;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==0&&m==0)
break;
int count=0;
for(i=0;i<n;i++)
scanf("%s",map[i]);
for(i=0;i<n;i++)
for(j=0;j<m;j++)
{
if(map[i][j]=='@')
{
map[i][j]='*';
BFS(i,j);
count++;
}
}
printf("%d\n",count);
}
return 0;
}
HDU 1240 Asteroids
链接:http://acm.hdu.edu.cn/showproblem.php?pid=1240
这是一道3维的BFS,在处理坐标时注意点,基本就可以过了,跟普通的宽搜没什么两样。
代码:
#include<cstdio>
#include<queue>
using namespace std;
struct point
{
int x,y,z,steps;
};
point start;
int dx,dy,dz;
int n;
char map[11][11][11];
int dir[6][3]={{1,0,0}, {-1,0,0}, {0,1,0}, {0,-1,0}, {0,0,1}, {0,0,-1}};
int bfs(point start)
{
queue<point>q;
int i;
point cur,next;
if(start.x==dx&&start.y==dy&&start.z==dz)//考虑起点和终点相同的情况
return 0;
start.steps=0;
map[start.x][start.y][start.z]='X';
q.push(start);
while(!q.empty())
{
cur=q.front();//取队首元素
q.pop();
for(i=0;i<6;i++) //广度优先搜索
{
next.x=cur.x+dir[i][0];
next.y=cur.y+dir[i][1];
next.z=cur.z+dir[i][2];
if(next.x==dx && next.y==dy && next.z==dz) //下一步就是目的地
{
return cur.steps+1;
}
if(next.x>=0&&next.x<n&&next.y>=0&&next.y<n&&next.z>=0&&next.z<n)//下一步不越界
if(map[next.x][next.y][next.z]!='X') //下一步不是星星
{
map[next.x][next.y][next.z]='X';
next.steps=cur.steps+1;
q.push(next);
}
}
}
return -1;
}
int main()
{
char str[10];
int i,j,step;
while(scanf("START %d",&n)!=EOF)
{
getchar();
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
for(int k=0;k<n;k++)
scanf("%c",&map[j][k][i]);
getchar();
}
}
scanf("%d%d%d",&start.x, &start.y, &start.z);
scanf("%d%d%d",&dx, &dy, &dz);
scanf("%s",str);
gets(str);
step=bfs(start);
if(step>=0)
printf("%d %d\n",n,step);
else
printf("NO ROUTE\n");
}
return 0;
}
HDU1372 Knight Movies
链接:http://acm.hdu.edu.cn/showproblem.php?pid=1372
这道题只要读懂题目就很容易可以搞定,是棋盘上马走的方向就是BFS搜索时的方向,棋盘是8*8,只不过用字母a到h表示。刚开始一直不明白题意,连样例都没看来,后来读懂之后真是个超级大水题。嘻嘻,这道题写的时候借用了下baka哥的头文件,感觉酷酷的样子,相信他不会怪我的吧,知道我这么水,也写不出什么好的头文件。
代码:
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<map>
#include<queue>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-8
#define pi acos(-1.0)
using namespace std;
int dir[8][2]={{1,2},{1,-2},{2,1},{2,-1},{-1,2},{-1,-2},{-2,-1},{-2,1}};
struct point
{
int x,y;
int step;
}start;
int dx,dy;
int visit[10][10];
int BFS(int x,int y)
{
int i;
queue<point> q;
point cur,next;
start.x=x;
start.y=y;
start.step=0;
q.push(start);
while(!q.empty())
{
cur=q.front();
q.pop();
if(cur.x==dx&&cur.y==dy)
return cur.step ;
for(i=0;i<8;i++)
{
next.x=cur.x+dir[i][0];
next.y=cur.y+dir[i][1];
if(next.x>=0&&next.x<8&&next.y>=0&&next.y<8&&!visit[next.x][next.y])
{
visit[next.x][next.y]=1;
next.step=cur.step+1;
q.push(next);
}
}
}
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
char a[3],b[3];
int sx,sy,sum;
while(scanf("%s%s",a,b)!=EOF)
{
printf("To get from %s to %s takes ",a,b);
sx=a[0]-'a';
sy=a[1]-'0'-1;
dx=b[0]-'a';
dy=b[1]-'0'-1;
memset(visit,0,sizeof(visit));
visit[sx][sy]=1;
sum=BFS(sx,sy);
printf("%d knight moves.\n",sum);
}
return 0;
}