问题 1465: [蓝桥杯][基础练习VIP]回形取数(dfs)

题目描述

回形取数就是沿矩阵的边取数,若当前方向上无数可取或已经取过,则左转90度。一开始位于矩阵左上角,方向向下。

输入

输入第一行是两个不超过200的正整数m, n,表示矩阵的行和列。接下来m行每行n个整数,表示这个矩阵。

输出

输出只有一行,共mn个数,为输入矩阵回形取数得到的结果。数之间用一个空格分隔,行末不要有多余的空格。

样例输入

3 3
1 2 3
4 5 6
7 8 9

样例输出

1 4 7 8 9 6 3 2 5


思路:

思路很简单,就是按照逆时针方向(下-右-上-左)不断遍历,直到某一个方向走到边界或者已被访问过后改变方向;

初代码 (这个代码没AC,可以直接跳过看后面)

这个代码不知道为什么没过,自己也没检查出什么错误。
(以后有时间再看看,有人看出来也可以评论告知一下)

#include <iostream>
#include <algorithm>
#include <string>
#include <queue>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;

int map[210][210];  //地图 
int m,n;
bool vis[210][210]={false};  //记录是否访问过 

vector<int> ans;     //记录答案
 
int dx[]={1,0,-1,0};    
int dy[]={0,1,0,-1};    /*按照取数的方向 下-右-上-左 这个顺序
                        一直循环取数,每个方向都是
                        取到不能取(即边界或者已取过),再改变方向*/ 
                        

int cnt=0;
void dfs(int x,int y,int direction)  /*用来表示当前方向,下-右-上-左
                                       分别用0123表示 */
{ 	
    if(cnt==n*m)
    return;
	vis[x][y]=1; 
	cnt++;  
	ans.push_back(map[x][y]); //记录答案
	
	if(direction==0)    //不断向下访问,直接访问不了,改变方向
	{
		while(1)
		{
			int newx=x+dx[0];
			int newy=y+dy[0];
			if(vis[newx][newy]==false && map[newx][newy])
			dfs(newx,newy,0);
			else break;
		}
		direction = 1;
	} 
	
	if(direction==1)   //不断向右访问,直接访问不了,改变方向
	{
		while(1)
		{
			int newx=x+dx[1];
			int newy=y+dy[1];
			if(vis[newx][newy]==false && map[newx][newy])
			dfs(newx,newy,1);
			else break;
		}
		direction = 2;
	} 
	
	if(direction==2)  //不断向上访问,直接访问不了,改变方向
	{
		while(1)
		{
			int newx=x+dx[2];
			int newy=y+dy[2];
			if(vis[newx][newy]==false && map[newx][newy])
			dfs(newx,newy,2);
			else break;
		}
		direction = 3;
	} 
	 
	if(direction==3)  // //不断向左访问,直接访问不了,改变方向
	{
		while(1)
		{
			int newx=x+dx[3];
			int newy=y+dy[3];
			if(vis[newx][newy]==false && map[newx][newy])
			dfs(newx,newy,3);
			else break;
		}
		direction = 0;
	} 
}


int main() 
{
    cin>>m>>n;
    for(int i=1;i<=m;i++)
      for(int j=1;j<=n;j++)
        cin>>map[i][j];
    
    dfs(1,1,0); 
    
    for(int i=0;i<ans.size();i++) //输出答案
    {
    	cout<<ans[i];
    	if(i<ans.size()-1)
    	cout<<" ";
	}
	return 0;
}

在这里插入图片描述在这里插入图片描述在这里插入图片描述
几种不同情况都是对的,代码明明就很ok嘛。。。


AC代码:

#include <iostream>
#include <algorithm>
#include <string>
#include <queue>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;

int map[210][210];  //地图 
int m,n;
bool vis[210][210]={false};  //记录是否访问过 

vector<int> ans;     //记录答案
 
int dx[]={1,0,-1,0};    
int dy[]={0,1,0,-1};    /*按照取数的方向 下-右-上-左 这个顺序一直循环取数
                        每个方向都是取到不能取(即边界或者已取过),再改变方向*/ 
                    
void dfs(int x,int y,int direction)//用来表示当前方向,下-右-上-左分别用0123表示 
{ 	
    
	vis[x][y]=1;  //标记访问过
	
	int newx=x+dx[direction]; //下一个点
	int newy=y+dy[direction];
	
   if(vis[newx][newy]==1 || newx<1 || newx>m || newy<1 || newy>n)       
   //访问过 或者 出边界(即到不了这个点)
    {
    	if(ans.size()==n*m) return; //如果取出的值等于n*m个,代表取完
        direction=(direction+1)%4; //改变方向
        dfs(x,y,direction);  //重新走这个点
    } 
    else //可以到达这个点
    {
        ans.push_back(map[newx][newy]);  //加入数组
        
        dfs(newx,newy,direction);    //继续遍历下一个点
    }
        
}

int main() 
{
    cin>>m>>n;
    for(int i=1;i<=m;i++)
      for(int j=1;j<=n;j++) //存图
        cin>>map[i][j];
    
    ans.push_back(map[1][1]); //放入第一个点
    dfs(1,1,0);
    
    for(int i=0;i<ans.size();i++) //输出答案
    {
    	cout<<ans[i];
    	if(i<ans.size()-1)
    	cout<<" ";
	}
	return 0;
}
发布了11 篇原创文章 · 获赞 15 · 访问量 320

猜你喜欢

转载自blog.csdn.net/weixin_45260385/article/details/105333716