搜索补全计划

搜索目录

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…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值