1.填涂颜色
这题我一开始的思路是0的左右上下都有1则给他填涂颜色,但是这样有些数据是过不了的,之前学长讲过这题思路反过来,将所有0都赋为2,然后从区域的四边的2开始搜,如果搜到2就把他变成0
#include<iostream>
#include<algorithm>
using namespace std;
int map[40][40];
int book[40][40];
int n;
int coun;
int nex[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
void dfs(int x,int y)
{
if(book[x][y])return;//该点已经走过
book[x][y]=1;//标记
int tx,ty;
for(int i=0;i<4;i++)//向左右上下搜2
{
tx=x+nex[i][0];
ty=y+nex[i][1];
if(tx>=0&&tx<=n&&ty>=0&&ty<=n&&map[tx][ty]!=1)//该点在地图内且不为1
{
if(map[tx][ty]==2)
map[tx][ty]=0;
dfs(tx,ty);
}
}
}
int main()
{
cin >> n;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
cin >> map[i][j];
if(map[i][j]==0)map[i][j]=2;//将所有的0变成2
}
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if((i==0||i==(n-1)||j==0||j==(n-1))&&map[i][j]==2&&book[i][j]==0)//只搜四边的2
dfs(i,j);
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
cout << map[i][j]<<' ';
cout <<endl;
}
}
2字母方阵
此题我一开始一个点从八个方向八条路一起走就导致一个字母与多个字母匹配,所以我们把方向改变放入主函数对一个点进行一个方向的搜,而且要注意的是要一直dfs到这条路可以走,我们才把它标记不然就会出现没成一个单词只是单词的一部分
#include<iostream>
#include<algorithm>
using namespace std;
char a[9]={"yizhong"};
char b[101][101];
char c[101][101];
bool vis[101][101];
int n;
int dx[8]={0,-1,0,1,-1,-1,1,1};
int dy[8]={-1,0,1,0,-1,1,-1,1};
void change(bool z[][101])//将b数组为单词的标记
{
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(vis[i][j]==1)b[i][j]='*';
}
int dfs(int yx,int yy,int x,int y,int fx,int fy,int i)//前面两个为一开始的原坐标,后面为走的路径还有方向和步数
{
if(i>6)//这个单词可以组成
{
vis[x][y]=1;//将第一个字母标记
vis[yx][yy]=1;//将最后一个标记
return 1;
}
int tx,ty;
tx=x+fx;
ty=y+fy;
if(tx>=0&&tx<n&&ty>=0&&ty<n&&c[tx][ty]==a[i])//在范围内且等于下一个字母
{
if(dfs(yx,yy,tx,ty,fx,fy,i+1))//往下面搜,判断最后是否搜到一个单词
{
vis[tx][ty]=1;//搜到就往回标记
return 1;
}
}
return 0;
}
int main()
{
cin >> n;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
cin >> b[i][j];
c[i][j]=b[i][j];
}
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
if(c[i][j]==a[0])
for(int c1=0;c1<8;c1++)//往八个反向搜
{
{
dfs(i,j,i,j,dx[c1],dy[c1],1);
}
}
}
change(vis);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
if(b[i][j]!='*')c[i][j]='*';
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
cout << c[i][j];
cout << endl;
}
}
3.玉米迷宫
这个其实就是个多个传送门的最短路径,用传统的bfs再加个判断此点是否可以传送,可以传送就把此点的传送位置入队
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int max_n=400;
char a[max_n][max_n];
bool vis[max_n][max_n];
int dx[4]={0,1,-1,0};
int dy[4]={1,0,0,-1};
queue<int>qx,qy,qs;
int m,n;
int startx,starty;//起点
int cx,cy;//出口
int match(int x,int y)//匹配传位
{
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
if(!(x==i&&y==j))//不与自己相等
if(a[x][y]==a[i][j])//找到传送点就给他入队
{
qx.push(i);
qy.push(j);
return 1;
}
return 0;
}
int bfs()
{
while(!qx.empty())
{
int tx=qx.front();
int ty=qy.front();
int ts=qs.front();
qx.pop();
qy.pop();
qs.pop();
if(tx==cx&&ty==cy)
return ts;
for(int i=0;i<4;i++)
{
int xx,yy;
xx=tx+dx[i];
yy=ty+dy[i];
int flag=0;
if(xx>=0&&xx<m&&yy>=0&&yy<n&&a[xx][yy]!='#'&&vis[xx][yy]==0&&a[xx][yy]>='A'&&a[xx][yy]<='Z')//此点没越界且没走过且为字母
if(match(xx,yy))//匹配
{qs.push(ts+1);vis[xx][yy]=1;flag=1;}
else vis[xx][yy]=1;//字母已经走过所以没有传送点还是标记
if(xx>=0&&xx<m&&yy>=0&&yy<n&&a[xx][yy]!='#'&&vis[xx][yy]==0&&!flag)//走草地
{qs.push(ts+1);qx.push(xx);qy.push(yy);vis[xx][yy]=1;}
}
}
return -1;
}
int main()
{
cin >>m>>n;
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
{
cin >>a[i][j];
if(a[i][j]=='@')
{
startx=i;
starty=j;
vis[i][j]=1;
}
if(a[i][j]=='=')
{
cx=i;
cy=j;
}
}
int step;
qx.push(startx);
qy.push(starty);
qs.push(0);
step= bfs();
cout <<step;
}