城堡问题(DFS)

 城堡问题(搜索) 
总时间限制: 1000ms 内存限制: 65536kB

描述 

(图 1)

# = Wall 
| = No wall 
- = No wall

图1是一个城堡的地形图。请你编写一个程序,计算城堡一共有多少房间,最大的房间有多大。城堡被分割成m*n(m≤50,n≤50)个方块,每个方块可以有0~4面墙。

输入 
程序从标准输入设备读入数据。第一行是两个整数,分别是南北向、东西向的方块数。在接下来的输入行里,每个方块用一个数字(0≤p≤50)描述。用一个数字表示方块周围的墙,1表示西墙,2表示北墙,4表示东墙,8表示南墙。每个方块用代表其周围墙的数字之和表示。城堡的内墙被计算两次,方块(1,1)的南墙同时也是方块(2,1)的北墙。输入的数据保证城堡至少有两个房间。

输出 
城堡的房间数、城堡中最大房间所包括的方块数。结果显示在标准输出设备上。

样例输入 


11 6 11 6 3 10 6 
7 9 6 13 5 15 5 
1 10 12 7 13 7 5 
13 11 10 8 10 12 13

样例输出 

9

例:11的二进制为1011,每一位二进制分别表示“南墙”“东墙”“北墙”“西墙”,为1表示有墙,为0表示没墙。
按位与运算符&的使用:如:11&4 <=> 1011 & 0100 = 0000 = 0。相同为1,不同为0。
竖式:1011
        &0100
           -----
           0000

解题思路:
对每个方块,深度优先搜索(DFS),从而给这个方块能够达到的所有位置染色。最后统计出一共有多少种颜色,以及每种颜色的数量。
比如:
1 1 2 2 3 3 3
1 1 1 2 3 4 3
1 1 1 5 3 5 3
1 5 5 5 5 5 3
从而一共有5个房间,最大的房间(1)占据9个格子。

【解法一:递归】

//AC
#include
#include
#include
using namespace std;
int R,C;    //行列数
int rooms[60][60];
int color[60][60];  //房间是否染色过的标记
int maxRoomArea=0,roomNum=0;
int roomArea;
//用递归解决:
void Dfs(int i,int k)
{
    if (color[i][k])
        return ;
    ++roomArea;
    color[i][k]=roomNum;
    if ((rooms[i][k]&1)==0)	
        Dfs(i,k-1); 	//向左走
    if ((rooms[i][k]&2)==0)
        Dfs(i-1,k); 	//向上走
    if ((rooms[i][k]&4)==0)
        Dfs(i,k+1); 	//向右走
    if ((rooms[i][k]&8)==0)
        Dfs(i+1,k); 	//向下走
}
int main()
{
    cin>>R>>C;
    for (int i=1;i<=R;i++)
        for (int k=1;k<=C;k++)
            cin>>rooms[i][k];
    memset(color,0,sizeof(color));
    for (int i=1;i<=R;i++)
    {
        for (int k=1;k<=C;k++)
        {
            if (!color[i][k])
            {
                ++roomNum;
                roomArea=0;
                Dfs(i,k);
                maxRoomArea=max(roomArea,maxRoomArea);
            }
        }
    }
    cout<
【解法二:堆栈】

/*这是一种仿照BFS模板的一种写法,O(∩_∩)O哈哈~,现在我终于明白BFS和DFS(堆栈解法)的区别了,其实套用BFS的模板一样可以实现DFS,说白了用堆栈写的DFS和用队列写的BFS只有一点不同,那就是它们所用的数据结构不同,就是因为这两种不同的数据结构的不同特性,才使得深搜和广搜效果不同。******堆栈为后进先出,这使得每次遍历时第一次也和广搜一样读入的第一步能走的节点,接下来会以栈顶元素为起点向下搜从该点一步能到的节点,但是每次查询的一个元素都是此次遍历的最后一个元素,也就是第二次查询的都是起点能到的下一层元素。******队列为先进先出,每次遍历时第一次也一样读入的第一步能走的节点,接下来会以队首元素为起点向下搜从该点一步能到的节点,但是每次查询时都是先查询一个元素都是上一层得元素,直到该层结束,在查下一层,因为上一层元素总是先入队的*/

//AC
#include
#include
#include
using namespace std;

int mark[60][60];
int room[60][60];
int n,m,num=0,area,maxarea;
struct data
{
    int x,y;
};

void dfs(int x,int y)
{
    stack stk;
    data p,pp;
    p.x=x;
    p.y=y;
    stk.push(p);
    while (!stk.empty())
    {
        p=stk.top();
        if (mark[p.x][p.y])
            stk.pop();
        else
        {
            ++area;
            mark[p.x][p.y]=1;
            if ((room[p.x][p.y]&1)==0&&p.y>0&&!mark[p.x][p.y-1])
            {
                pp.x=p.x;
                pp.y=p.y-1;
                stk.push(pp);
            }
            if ((room[p.x][p.y]&2)==0&&p.x>0&&!mark[p.x-1][p.y])
            {
                pp.x=p.x-1;
                pp.y=p.y;
                stk.push(pp);
            }
            if ((room[p.x][p.y]&4)==0&&p.y+1maxarea)
                        maxarea=area;
                }
            }
        }
        printf("%d\n%d\n",num,maxarea);
    }
    return 0;
}

【解法三:其实这也是用堆栈解决的,只是里面用的结构体内的构造函数,而不是两个结构体变量】

#include 
#include 

using namespace std;

int m, n, roomNum = 0, curRoomAera;
int map[50][50], color[50][50] = {0};

struct Room
{
    int x, y;
    Room(int x, int y):x(x),y(y) {}
};
//用栈解决:
void dfs(int X, int Y)
{
    stack stk;
    stk.push(Room(X, Y));
    int x, y;
    while (!stk.empty())
    {
        Room topRoom = stk.top();
        x = topRoom.x;
        y = topRoom.y;
        if (color[x][y])
            stk.pop();
        else
        {
            curRoomAera++;
            color[x][y] = roomNum;	//标记栈顶元素
	    //坑爹啊......&(按位与)运算符的优先级小于 == ,所以必须加括号
            if (((map[x][y] & 1) == 0) && (y > 0) && !color[x][y-1])	//千万注意!&1==0时对应的一定是y-1,即必须向左走
                stk.push(Room(x, y-1));    
            if (((map[x][y] & 2) == 0) && (x > 0) && !color[x-1][y])	//千万注意!&2==0时对应的一定是x-1,即必须向上走	
                stk.push(Room(x-1, y));  
            if (((map[x][y] & 4) == 0) && (y+1 < n) && !color[x][y+1])	//千万注意!&4==0时对应的一定是y+1,即必须向右走
                stk.push(Room(x, y+1));
            if (((map[x][y] & 8) == 0) && (x+1 < m) && !color[x+1][y])	//千万注意!&8==0时对应的一定是x+1,即必须向下走
                stk.push(Room(x+1, y));
        }
    }
}

int main()
{
    int maxRoomAero = 0;
    cin >> m >> n;
    for( int i = 0; i < m; i++)
        for (int j = 0; j < n; j++)
            cin >> map[i][j];
    for( int i = 0; i < m; i++)
        for (int j = 0; j < n; j++)
            if (!color[i][j])
            {
                roomNum++;
                curRoomAera = 0;
                dfs(i, j);
                if (curRoomAera > maxRoomAero)
                    maxRoomAero = curRoomAera;
            }
    cout << roomNum << endl << maxRoomAero <



你可能感兴趣的:(搜索(BFS)(DFS),算法)