Weed (DFS)

来源:互联网 发布:淘宝沙河力度 编辑:程序博客网 时间:2024/05/16 12:47

Weed

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other)
Total Submission(s) : 41   Accepted Submission(s) : 13
Problem Description
Andrew has visited his garden for the last time many years ago. Today's property taxes are so high, so Andrew decided to sell his garden. The land was not cultivated for a long time and now it is probably a lot of weed on it. Andrew wants to remove everything from the ground before selling. Now he wants to estimate the amount of work.The garden has the rectangular form and is divided into  equal squares. Andrew's memory is phenomenal. He remembers which squares were occupied by the weed. For the purpose of simplicity, Andrew thinks that each square is either fully occupied by the weed or completely free from it. Andrew likes botany and he knows that if some square is free from the weed but at least two of its adjacent squares are occupied by the weed (two squares are adjacent if they have common side), that square will be also occupied by the weed soon. Andrew is pretty sure that during last years weed occupied every square possible. Please help Andrew to estimate how many squares is occupied by the weed.
Input
The first line of the input contains integers N and M (1 ≤ NM ≤ 1000). Next N lines contain M characters each. Character X denotes that the corresponding square is occupied by the weed. A period character (

.) denotes an empty square.

Output
Print one integer denoting the number of squares occupied by the weed after so many years.
Example(s)

sample input

sample output

3 3 X.. .X. .X.

6

sample input

sample output

3 4 X..X .X.. .X..

12

 
Statistic | Submit | Back

题目大意:

有一片网格空地,有杂草,也有干净的土地。已知如果一个干净的土地四个方向的邻接土地有两个或者两个以上为杂草,那么它也会变成杂草。

给定一个地图,问一共会有多少块生长杂草的地面。

题目思路:

这道题目想了好久,虽然是简单的搜索。但是,奈何我还是不会,莫非还是没摸到搜索的窍门。但是还是要多做。

我一开始的思路是把全图遍历一边,用DFS,遇到是空地且周围有两个杂草地的,就计数一个,并把它变为杂草,对于,一开始我所占的土地是空地,但是因为下一个扩展点的地面变成杂草之后,我站的地面可以变为杂草,这样的情况我是利用DFS回溯的性质,把之前走过的再检查一遍。但是很可惜,TE了。估计还是我的方法不行,因为找不到什么别的剪枝的方法了,如果你能有新的剪枝方法,一定要私信我

代码如下:

#include<stdio.h>#include<string.h>bool vis[3000][3000];char map[3000][3000];int N,M;int count;int x_move[4] = {-1, 0, 1, 0};int y_move[4] = {0, 1, 0, -1};int is_ok(int x,int y){    int i;    int sum=0;    for(i=0;i<4;i++)        if(map[x+x_move[i]][y+y_move[i]]=='X')            sum++;    return sum;}void DFS(int x,int y){    int i,j;    int tx,ty;    if(is_ok(x,y)>=2&&(x==1&&y==1)&&map[x][y]=='.')    {        map[x][y]='X';        count++;    }    for(i=0;i<4;i++)    {        tx=x+x_move[i];        ty=y+y_move[i];        if(tx<1||tx>N||ty<1||ty>M)            continue;        if(vis[tx][ty]==0)        {            vis[tx][ty]=1;            if(is_ok(tx,ty)>=2&&map[tx][ty]=='.')            {                count++;                map[tx][ty]='X';            }            DFS(tx,ty);            vis[tx][ty]=0;            if(is_ok(tx,ty)>=2&&map[tx][ty]=='.')            {                count++;                map[tx][ty]='X';            }        }    }}int main(){    int i,j;    int a,b;    while(scanf("%d%d",&N,&M)!=EOF)    {        getchar();        count=0;        int flag=1;        memset(vis,0,sizeof(vis));        for(i=1;i<=N;i++)        {            for(j=1;j<=M;j++)            {                scanf("%c",&map[i][j]);            //    if(map[i][j]=='.'&&flag==1){a=i;b=j;flag=0;vis[i][j]=1;}                if(map[i][j]=='X')count++;            }            getchar();        }        DFS(1,1);        printf("%d\n",count);    }    return 0;}

后来更正思路,采取这样的做法,先遍历图一次,如果我碰到可以由空地变为杂草的点,把他变为杂草之后,那么我以这个点为起点进行搜索,如果他的四个方向中有空地可以变成杂草的话,那么继续搜索,这样做就是为了处理之前走过的土地一开始不能变为杂草,但是现在可以的情况。如果该地面不能变为杂草,那么回溯。

其实第一次遍历图的目的是计算,原图中可以变为杂草的点,DFS的作用就是,当增加新的杂草点的时候,进行扩展,看有没有因为新增加的杂草地面而有更多的,空地变为杂草

最后遍历图一次,找是X的点,计数输出。



代码如下:




#include<stdio.h>#include<string.h>bool vis[3000][3000];char map[3000][3000];int N,M;int count;int x_move[4] = {-1, 0, 1, 0};int y_move[4] = {0, 1, 0, -1};int is_ok(int x,int y){int i;int sum=0;if(map[x][y]=='X')return 0;for(i=0;i<4;i++){if(map[x+x_move[i]][y+y_move[i]]=='X')sum++;if(sum>=2)map[x][y]='X';}if(sum>=2)return 1;elsereturn  0;}void DFS(int x,int y){int i,j;int tx,ty;for(i=0;i<4;i++){tx=x+x_move[i];ty=y+y_move[i];if(tx<0||tx>=N||ty<0||ty>=M)continue;if(map[tx][ty]=='.'){if(is_ok(tx,ty))DFS(tx,ty);}}}int main(){int i,j;while(scanf("%d%d",&N,&M)!=EOF){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(is_ok(i,j)) DFS(i,j);for(i=0;i<N;i++)for(j=0;j<M;j++)if(map[i][j]=='X')count++;printf("%d\n",count);}return 0;}



再次贴上一份队里面大神的代码,很简洁。值得学习,我的代码一直很烂:



#include<stdio.h>int n,m;char map[1001][1001];int dir[4][2]={0,1,0,-1,1,0,-1,0};int ok(int x,int y){    int i,cnt=0;    if(map[x][y]=='X')  return 0;    for(i=0;i<4;i++)    {        int xx=x+dir[i][0];        int yy=y+dir[i][1];        if(xx>=0&&x<n&&yy>=0&&yy<m)        {            if(map[xx][yy]=='X') cnt++;        }    }    if(cnt>=2) {map[x][y]='X';return 1;}    return 0;}void DFS(int x,int y){    int i;    for(i=0;i<4;i++)    {        int xx=x+dir[i][0];        int yy=y+dir[i][1];        if(xx>=0&&x<n&&yy>=0&&yy<m)        {            if(map[xx][yy]=='.')                if(ok(xx,yy)) DFS(xx,yy);        }    }}int main(){    int i,j;    while(scanf("%d %d",&n,&m)!=EOF)    {        for(i=0;i<n;i++)            scanf("%s",map[i]);        for(i=0;i<n;i++)            for(j=0;j<m;j++)               if(ok(i,j))  DFS(i,j);        int ans=0;        for(i=0;i<n;i++)            for(j=0;j<m;j++)              if(map[i][j]=='X') ans++;        printf("%d\n",ans);     }    return 0;}


原创粉丝点击