DFS专题+BFS复习

A题:Red and Black

题意:从起始点出发,遇到坑不走,问能够到达的点有多少个。

思路:板子题。DFS或者BFS都可以

DFS:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define clr(a) memset(a,0,sizeof(a))


const int MAXN = 1e5+10;
const int INF = 0x3f3f3f3f;
const int N = 30;

int n,m,sum;
char mapp[N][N];
int vis[N][N];
int dx[4] = {1,-1,0,0};
int dy[4] = {0,0,1,-1};

bool check(int x,int y){
    if(x<0||x>=n||y<0||y>=m||mapp[x][y]=='#'){
        return false;
    }
    else return true;
}
void DFS(int x,int y){
    if(!check(x,y)||vis[x][y]){
        return ;
    }
    else{
        sum++;
        int fx,fy;
        for(int i=0;i<4;i++){
            vis[x][y] = true;
            fx = x + dx[i];
            fy = y + dy[i];
            DFS(fx,fy);
        }
    }
}
int main(){
    while(scanf("%d%d",&m,&n)!=EOF&&(n||m)){
        clr(mapp);clr(vis);
        sum = 0;
        for(int i=0;i<n;i++){
            scanf("%s",mapp[i]);
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(mapp[i][j] == '@'){
                    //cout<<i<<"   "<<j<<endl;
                    DFS(i,j);
                    break;
                }
            }
        }
        printf("%d\n",sum);
    }
    return 0;
}

BFS:

#include<bits/stdc++.h>
using namespace std;
#define clr(a) memset(a,0,sizeof(a))

const int N = 30;


int n,m,sum;
char mapp[N][N];
bool vis[N][N];
int dir[2][4] = { {1,-1,0,0}, {0,0,1,-1} };

bool check(int x,int y){
    if(mapp[x][y]=='#'||x<0||x>=n||y<0||y>=m)
        return false;
    else return true;
}
struct node{
    int x,y;
};
queue<node>Q;
void BFS(int x,int y){
    node o;
    o.x = x;
    o.y = y;
    Q.push(o);
    vis[x][y] = true;
    while(!Q.empty()){
        sum ++;
        o = Q.front();
        Q.pop();
        for(int i=0;i<4;i++){
            int tx = o.x + dir[0][i];
            int ty = o.y + dir[1][i];
            if(check(tx,ty)&&!vis[tx][ty]){
                node w ;
                w.x = tx;w.y = ty;
                Q.push(w);
                vis[tx][ty] = true;
            }
        }
    }
}
int main(){
    while(scanf("%d%d",&m,&n)!=EOF&&(n||m)){
        clr(mapp);clr(vis);
        sum = 0;
        while(!Q.empty()) Q.pop();
        for(int i=0;i<n;i++){
            scanf("%s",mapp[i]);
        }

        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(mapp[i][j]=='@'){
                    BFS(i,j);
                    break;
                }
            }
        }
        cout<<sum<<endl;
    }
    return 0;
}

——————————————————————————————————————————————————————

B题:Tempter of the Bone

题意:问小狗是否能在第T分钟的时候恰好到达出口离开迷宫。

思路:本来想着用BFS,后来想想BFS求出的结果是最短路,但是在这道题里,最短路不一定就是T时间,所以BFS不可用,应               该用DFS顺便记录时间。

正解:DFS + 剪枝

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define clr(a) memset(a,0,sizeof(a))


const int MAXN = 1e5+10;
const int INF = 0x3f3f3f3f;
const int N = 55;

int n,m,T,dis;
int tx ,ty,sx,sy;
char mp[N][N];
bool vis[N][N],flag;
int dir[2][4]={ {1,-1,0,0},{0,0,1,-1} };

bool check(int x,int y){
    if(x>=0&&x<n&&y>=0&&y<m)    return true;
    else return false;
}
void DFS(int x,int y,int t){
    vis[x][y] = 1;
    if(mp[x][y]=='D'&&t==T){
        flag = 1;return;
    }
    //奇偶剪枝
    int temp = T - t - (abs(x-tx)+abs(y-ty));
    if(temp<0||(temp&1))  return ;
    for(int i=0;i<4;i++){
        int dx = x+dir[0][i];
        int dy = y+dir[1][i];
        if(check(dx,dy)&&!vis[dx][dy]&&mp[dx][dy]!='X'){
            DFS(dx,dy,t+1);
            if(flag)    return ;
            //回溯
            vis[dx][dy] = false;
        }
    }
}
int main(){
    while(scanf("%d%d%d",&n,&m,&T)!=EOF&&(n||m||T)){
        clr(vis);clr(mp);
        flag = false;
        dis = 0;
        for(int i=0;i<n;i++){
            scanf("%s",mp[i]);
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(mp[i][j]=='D'){
                    tx = i;ty = j;
                }
                if(mp[i][j]=='S'){
                    sx = i;sy = j;
                }
            }
        }
        dis = abs(sx-tx)+abs(sy-ty);
        DFS(sx,sy,0);
        if(flag)    cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
    return 0;
}

 

——————————————————————————————————————————————————————

C题:Oil Deposits

思路:DFS的板子题。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;
int n,m;
char s[110][110];
int mapp[110][110];
int xx[8]={-1,1,0,0,-1,-1,1,1};
int yy[8]={0,0,-1,1,-1,1,-1,1};


void dfs(int a,int b){
    if(a<0||a>=n||b<0||b>=m||mapp[a][b]==0){
        return ;
    }
    mapp[a][b]=0;
    for(int i=0;i<8;i++){
        int na=a+xx[i];
        int nb=b+yy[i];
        dfs(na,nb);
    }
}
//0是*    1是@   0 是墙    1是路 
int main(){
    while(~scanf("%d%d",&n,&m)&&(n!=0&&m!=0)){
        memset(mapp,0,sizeof(mapp));
        memset(s,0,sizeof(s));
        getchar();
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                scanf("%c",&s[i][j]);
                if(s[i][j]=='*')
                    mapp[i][j]=0;
                else
                    mapp[i][j]=1;
            }
            getchar();
        }
        int ans=0;
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(mapp[i][j]==1){
                    dfs(i,j);
                    ans++;
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

——————————————————————————————————————————————————————

D题:How Many Equations Can You Find

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
char s[10000];
long long n,ans,len;
void dfs(int sum,int id)  {  
    if(id==len)  {  
        if(sum==n) {
            ans++; 
        }      
        return ;  
    }  //判断是否是最后一个数 
    long long temp=0;  
    for(int i=id;i<len;i++)  {  
        temp=temp*10+(s[i]-'0');  
        dfs(sum+temp,i+1);  
        if(id!=0)  
            dfs(sum-temp,i+1);  
    }  
} 

int main()  {  
    while(scanf("%s%lld",s,&n)!=EOF)  {  
        ans=0;  
        len=strlen(s);  
        dfs(0,0);  
        printf("%lld\n",ans);  
    }
   return 0;  
} 

 

——————————————————————————————————————————————————————

E题:Fox And Two Dots

题意:判断图中,相同颜色是否能成环。

思路:DFS + 标记

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define clr(a) memset(a,0,sizeof(a))


const int MAXN = 1e5+10;
const int INF = 0x3f3f3f3f;
const int N = 55;

int n,m,num,fx,fy;
bool vis[N][N];
char mp[N][N];
int flag = 0;
int dir[2][4] = { {1,-1,0,0} ,{0,0,1,-1} };
bool check(int x,int y){
    if(x>=0&&x<n&&y>=0&&y<m)
        return true;
    else return false;
}
void DFS(int x,int y,int fx,int fy,char s){
    vis[x][y] = true;
    for(int i=0;i<4;i++){
        int dx = x+dir[0][i];
        int dy = y+dir[1][i];
        if(check(dx,dy)&&mp[dx][dy]==s){
            if(dx==fx&&dy==fy)  continue;//如果是上一个点则跳过
            else{
                if(vis[dx][dy]){//如果这个点之前被标记过,说明成环了
                    flag = 1;
                    return;
                }
                vis[dx][dy] = true;
                DFS(dx,dy,x,y,s);
            }
        }
    }
}
int main(){
    cin>>n>>m;
    clr(mp);clr(vis);
    flag = 0;
    for(int i=0;i<n;i++){
        scanf("%s",mp[i]);
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            if(!vis[i][j]){
                DFS(i,j,-1,-1,mp[i][j]);
                if(flag == 1){
                    cout<<"Yes"<<endl;
                    return 0;
                }

            }
        }
    }
    if(!flag)
        cout<<"No"<<endl;
    return 0;
}

——————————————————————————————————————————————————————

F题:Lakes in Berland

思路:用两个数组s[][],mapp[][]。s数组用来跑dfs并且记录湖泊数目与其面积,然后将数据传入结构体。但是跑完dfs之后,s数组就已经被填充完了,不能按照题目要求输出。所以用到了第二个mapp[][]数组,在按照题目要求填充湖泊(跑dfs1)之后,就可以按照顺序输出了。

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;
int n,m,k;
int xx[4]={-1,1,0,0};
int yy[4]={0,0,-1,1};
char s[110][110];
char mapp[110][110];
int ans=0;
struct node{
    int x;
    int y;//   x,y 分别储存相应的横纵坐标
    int num;   //   num储存有多少个湖泊块
}p[3000];//要大于2500,因为这个WA了一遍。
bool cmp(node a,node b){
    return a.num < b.num;
}//按  从小到大的顺序排序。
void dfs(int a,int b){
    if(a<0||a>=n||b<0||b>=m||s[a][b]=='*')
        return ;
    p[ans].num++;//记录湖泊的大小
    s[a][b]='*';
    for(int i=0;i<4;i++){
        int na=a+xx[i];
        int nb=b+yy[i];
        dfs(na,nb);
    }
}//这个用于s[][]跑dfs,顺便记录一下每个湖泊的位置和大小。(同一个湖泊只记录了一次)
void dfs2(int a,int b){
    if(a<0||a>=n||b<0||b>=m||s[a][b]=='*')
        return ;
    s[a][b]='*';
    for(int i=0;i<4;i++){
        int na=a+xx[i];
        int nb=b+yy[i];
        dfs(na,nb);
    }
}//这个dfs 用于填充海洋
void dfs1(int a,int b){
    if(a<0||a>=n||b<0||b>=m||mapp[a][b]=='*')
        return ;
    mapp[a][b]='*';
    for(int i=0;i<4;i++){
        int na=a+xx[i];
        int nb=b+yy[i];
        dfs1(na,nb);
    }
}//这个dfs 用于最后mapp[][] 按照已经给出的坐标开始填充湖泊
int main(){
    while(~scanf("%d%d%d",&n,&m,&k)){
        ans=0;
        getchar();//消回车
        memset(s,0,sizeof(s));
        memset(mapp,0,sizeof(mapp));//数组清零
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                scanf("%c",&s[i][j]);
                mapp[i][j]=s[i][j];
            }
            getchar();//消回车
        }
        int i,j;//开始填充海洋
        j=0;
        for(i=0;i<n;i++)
            if(s[i][j]=='.')
                dfs2(i,j);
        j=m-1;
        for(i=0;i<n;i++)
            if(s[i][j]=='.')
                dfs2(i,j);
        i=0;
        for(j=0;j<m;j++)
            if(s[i][j]=='.')
                dfs2(i,j);
        i=n-1;
        for(j=0;j<m;j++)
            if(s[i][j]=='.')
                dfs2(i,j);
        //填充海洋结束
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(s[i][j]=='.'){
                    p[ans].x=i;
                    p[ans].y=j;//记录湖泊的坐标
                    p[ans].num=0; //记录湖泊大小
                    dfs(i,j);//用s[][]跑dfs
                    ans++;//记录湖泊的个数
                }
            }
        }
     //   printf("%d!!!\n",ans);
        int sum=0;
        sort(p,p+ans,cmp);//按照湖泊从小到大排序
        for(int i=0;i<ans-k;i++){
            dfs1(p[i].x,p[i].y);
            sum+=p[i].num;
        }
        printf("%d\n",sum);//输出需要填充的湖泊的总面积
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                printf("%c",mapp[i][j]);
            }//输出填充后的湖泊
            printf("\n");
        }
    }
    return 0;
}

 

——————————————————————————————————————————————————————

G题:棋盘问题

#include<cstdio>
#include<cstring> 
int n,k;
char mapp[20][20];
bool vis[20];
int ans=0;
void dfs(int x,int cur){
	if(cur==k)//完全填入一次加1 
		ans++;
	for(int k=x;k<n;k++)//选择填入第几行的棋盘 
	{
		for(int i=0;i<n;i++)//看哪一个是棋盘 
		{
			if(mapp[k][i]=='#' && vis[i]==false)//回溯 
			{
				vis[i]=true;
				dfs(k+1,cur+1);
				vis[i]=false;
			}
		}
	}
	
}
int main(){
	while(scanf("%d%d",&n,&k)!=EOF&&n!=-1&&k!=-1){
		ans=0;
		memset(vis,false,sizeof(vis));
		for(int i=0;i<n;i++)
			scanf("%s",mapp[i]);
		dfs(0,0);
		printf("%d\n",ans);
	}
	return 0;
} 

 

——————————————————————————————————————————————————————

 

H题:The Game

别说了兄弟, 这题是真**恶心。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define LL long long
#define clr(a) memset(a,0,sizeof(a))

const int MAXN = 1e6+10;
const int INF = 0x3f3f3f3f;
const int N = 101;

int n,m,ans,cnt;
int x1,y2,x2;
int y1;
char mp[N][N];
bool vis[N][N];
int minn = MAXN;
int dir[2][4] = { {1,-1,0,0} , {0,0,1,-1} };
struct node{
    int x,y,step;
};
bool check(int x,int y){
    if(x>=0&&x<=n+1&&y>=0&&y<=m+1)
        return true;
    else return false;
}
void BFS(){
    memset(vis,false,sizeof(vis));
    node u,v;
    queue<node>Q;
    u.x = x1;u.y = y1;u.step = 0;
    vis[u.x][u.y] = true;
    Q.push(u);
    while(!Q.empty()){
        u = Q.front();
        Q.pop();
        if(u.x == x2&&u.y == y2){
            minn = min(u.step,minn);
        }
        for(int i=0;i<4;i++){
            v.x = u.x+dir[0][i];
            v.y = u.y+dir[1][i];
            while(check(v.x,v.y)&&!vis[v.x][v.y]&&(mp[v.x][v.y]==' '||(v.x==x2&&v.y==y2))){
                vis[v.x][v.y] = true;
                v.step = u.step + 1;
                Q.push(v);
                v.x += dir[0][i];
                v.y += dir[1][i];
            }
        }
    }
}
int main(){
    int num = 1;
    while(scanf("%d%d",&m,&n)!=EOF&&(n||m)){
        clr(vis);
        for(int i=0;i<=n+1;i++){
            for(int j=0;j<=m+1;j++){
                mp[i][j] = ' ';
            }
        }
        getchar();
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                scanf("%c",&mp[i][j]);
            }
            getchar();
        }
        cout<<"Board #"<<num++<<':'<<endl;
        cnt = 1;
        while(scanf("%d%d%d%d",&y1,&x1,&y2,&x2)&&(y1||y2||x1||x2)){
            minn = INF ;
            cout<<"Pair "<<cnt++<<": ";
            BFS();
            if(minn==INF) cout<<"impossible.\n";
			else cout<<minn<<" segments.\n";
        }
        cout<<endl;
    }
    return 0;
}
/*
5 4
XXXXX
X   X
XXX X
 XXX
2 3 5 3
1 3 4 4
2 3 3 4
0 0 0 0

*/

——————————————————————————————————————————————————————

I题:放苹果

#include<bits/stdc++.h>
using namespace std;

int DFS(int m,int n)  {
    if(m == 0 || n == 1)
        return 1;
    else if(n > m)
        return DFS(m, m);
    else
        return DFS(m - n, n) + DFS(m, n - 1);
}
int main(void)  {
    int t, m, n;
    scanf("%d", &t);
    while(t--) {
        scanf("%d%d", &m, &n);
        printf("%d\n", DFS(m, n));
    }
    return 0;
}

 

——————————————————————————————————————————————————————

K题:迷宫问题

思路:BFS+记录路径

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;

const int MAX = 1e6+10;
const int INF = 0x3fffffff;
int way[15][15];
int mapp[15][15];
int vis[15][15];

struct node{
	int x,y;
}p[210];
int dir[4][2]={0,1,1,0,-1,0,0,-1};
void BFS(int x,int y){
	queue <node> q;
	memset(vis,0,sizeof(vis));
	memset(way,0,sizeof(way));
	node cnt;
	cnt.x=x;
	cnt.y=y;
	way[x][y]=0;//标记下起点的步数为0 
	q.push(cnt);//把起点入队列 
	vis[x][y]=1;//标记起点已经来过了 
	while(!q.empty()){
		node ts = q.front();
		q.pop();
		if(ts.x==5&&ts.y==5)	return;//如果已经找到右下角点则跳出 
		for(int i=0;i<4;i++){
			int x1 = ts.x+dir[i][0];
			int y1 = ts.y+dir[i][1];
			if(!vis[x1][y1]&&mapp[x1][y1]==0&&x1>=1&&x1<=5&&y1>=1&&y1<=5){
                //如果该位置不是墙,且之前没有走过 
				vis[x1][y1]=1;//标记走过 
				way[x1][y1]=way[ts.x][ts.y]+1;//标记一下步数 
				node temp;
				temp.x=x1;
				temp.y=y1;
				q.push(temp);// 把新到的点入队列 
			}
		}
	}
}
void print(node a,node b){
	if(a.x==b.x&&a.y==b.y)	return ;//如果走到了右下点则结束 
	for(int i=0;i<4;i++){
		int x1 = b.x+dir[i][0];
		int y1 = b.y+dir[i][1];
		if((way[b.x][b.y]==way[x1][y1]+1)&&vis[x1][y1]){
			node temp;
			temp.x=x1;
			temp.y=y1;
			 print(a,temp);  
			printf("(%d, %d)\n",temp.x-1,temp.y-1);
		}
	}
	return ;
}
int main(){
	memset(mapp,0,sizeof(mapp));
	memset(p,0,sizeof(p));
	for(int i=1;i<6;i++){
		for(int j=1;j<6;j++){
			scanf("%d",&mapp[i][j]);
		}
	}
	BFS(1,1);
	node pre;
	node last;
	pre.x=1;pre.y=1;
	last.x=5;last.y=5;
	print(pre,last);
	printf("(4, 4)\n");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/l18339702017/article/details/81280637