DFS
Lake Counting
有一个大小为N*M的园子,雨后积水。八连通的积水被认为是连接在一起的。请求出园子里总共有多少水洼?(八连通指的是下图中相对W的.部分)
…
.w.
…
input :N=10,M=12.
w … … . . ww .
. www … . . www
… . ww … ww .
… … … ww .
… … … w . .
. . w … … w . .
. w . w … . . ww .
w . w . w … . . w .
. w . w … … w
. . w … … . w .
input :3
从任意w开始,不停把邻接部分用’.’代替。一次DFS后与初始的这个w连接的所有w就都被替换成了’.’,直到图中不再存在w为止,总共进行DFS的次数就是答案了。八个方向共对应了8种状态转移,每个格子DFS参数至多被调用一次。
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#define DIRECTSIZE 8
struct direct {
int drow;
int dcol;
} direct[DIRECTSIZE] =
{{0, -1}, {0, 1}, {-1, 0}, {1, 0}, {-1, -1}, {-1, 1}, {1, -1}, {1, 1}};
#define MAXN 100
char grid[MAXN+2][MAXN+2];
void dfs(int row, int col)
{
int i;
for(i=0; i<DIRECTSIZE; i++) {
int nextrow = row + direct[i].drow;
int nextcol = col + direct[i].dcol;
if(grid[nextrow][nextcol] == 'W') {
grid[nextrow][nextcol] = '.';
dfs(nextrow, nextcol);
}
}
}
int main(void)
{
int m, n, count, i, j;
while(scanf("%d%d", &m, &n) != EOF) {
memset(grid, 0, sizeof(grid));
for(i=1; i<=m; i++)
scanf("%s", grid[i]+1);
count = 0;
for(i=1; i<=m; i++)
for(j=1; j<=n; j++)
if(grid[i][j] == 'W') {
count++;
grid[i][j] = '.';
dfs(i, j);
}
printf("%d\n", count);
}
return 0;
}
DFS
A - 棋盘问题 POJ - 1321
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
——————————————————————————————————————————
Input
输入含有多组测试数据。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
——————————————————————————————————————————
Output
对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。
——————————————————————————————————————
Sample Input
2 1
#.
.#
4 4
…#
..#.
.#..
#…
-1 -1
————————————————————————————————————————
Sample Output
2
1
啊。题意要先理解空白部分和棋盘区域,空白位置不是让你放棋子的,棋盘位置才是。思路大概,对每一行递归那么只用考虑单独行,搜索每一列从而只考虑当前位置。注意在试过一个位置后需要清除当前的标记。那就成了简单的dfs了。
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <stack>
#include <queue>
#include <string>
#include <cstring>
#include <vector>
#include <set>
using namespace std;
const int maxn = 1e5+10;
char s[10][10],vis[10];
int ans=0,sum=0,n,k;
void dfs (int t){
if(sum==k){
ans++;
return ;
}
if(t>=n) return ;
//以上为判断当前位置的退出条件,而非单单完成dfs的条件
for(int i=0;i<n;i++){//列搜索
if(!vis[i]&&s[t][i]=='#'){
vis[i]=1;
sum++;
dfs(t+1);//判断下一行各点
vis[i]=0;
sum--;
}
}
dfs(t+1);//行递归
}
int main(void)
{
while(~scanf("%d%d",&n,&k)){
if(n==-1&&k==-1)break;
memset(vis,0,sizeof(vis));
sum=0,ans=0;
for(int i=0;i<n;i++)
scanf("%s",s[i]);
dfs(0);
printf("%d\n",ans);
}
return 0;
}
BFS
* POJ3984 迷宫问题*
定义一个二维数组:
int maze[5][5] = {
0, 1, 0, 0, 0,
0, 1, 0, 1, 0,
0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 1, 0,
};
Input
一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。
Output
左上角到右下角的最短路径,格式如样例所示。
Sample Input
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
Sample Output
(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)
它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。
啊。BFS的入门题,主要的知识点自然是BFS框架(使用queue)以及路径的储存,代码的框架需要理解记忆。
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <stack>
#include <queue>
#include <string>
#include <cstring>
#include <vector>
#include <set>
using namespace std;
const int maxn = 5;
struct direct {
int x,y;
}direct[4]={{0,1},{1,0},{0,-1},{-1,0}};//方向数组
int mapp[maxn+2][maxn+2];//图
struct node {
int row,col;
};
node father[maxn+2][maxn+2];//记录路径
//stack <node> ans ;
queue <node>q;
void bfs (){
node start;
start.row = 1;
start.col = 1;//防止数组越界
q.push(start);
while(!q.empty()){
node x =q.front(); q.pop();
if(x.col==5&&x.row==5){
//输出
node pass[1000];//记录路径
pass[0].row=5;pass[0].col=5;
int i;
for(i=0;;i++){
if(pass[i].row==1&&pass[i].col==1) break;
pass[i+1]=father[pass[i].row][pass[i].col];
}
for(int j=i;j>=0;j--){
printf("(%d, %d)\n",pass[j].row-1,pass[j].col-1);
}
return ;
}
for(int i=0;i<4;i++){//节点展开
node nextt;
nextt.row= x.row+direct[i].x;
nextt.col= x.col+direct[i].y;
if(mapp[nextt.row][nextt.col]==0){
father[nextt.row][nextt.col]= x;
q.push(nextt);//压入队列,之后以当前节点展开
}
}
mapp[x.row][x.col] = 1;//搜索过的标记
}
}
int main()
{
for(int i=0;i<maxn+2;i++){
mapp[0][i] = 1;
mapp[maxn+1][i] = 1;
mapp[i][0] = 1;
mapp[i][maxn+1] = 1;
}
for(int i=1;i<=maxn;i++){
for(int j=1;j<=maxn;j++){
scanf("%d",&mapp[i][j]);
}
}
bfs();
return 0;
}
初学时参考了大神的代码
more..more…