题意:
有一个 n×m 的矩阵 a。对一个矩阵进行变换,定义为将这个矩阵内的所有元素变为其上下左右四个元素(不存在则忽略)及自身的最大公约数。询问 a[x][y] 在进行最少多少次变换之后会变成 11。如果可以使 a[x][y] 经过若干次变换变成 11,输出其中最小的次数;否则输出 -1。
蒟蒻的第一想法当然是暴力啦,但是我转念一想,第一轮只依靠自己,第二轮扩散,第三轮再扩散。
这不就是个BFS吗?!(注意到遍历全图只用 O(),完全够啊)
那如果满了呢,那就不行啦
献上代码:(记得看注释)
#include<bits/stdc++.h>
#define int long long
using namespace std;
struct node{
int nowx,nowy,now; //分别表示目前位置与目前次数
};
int n,m,x,y;
int a[2010][2010];
bool vis[2010][2010];
int dx[4] = {0,1,0,-1};
int dy[4] = {1,0,-1,0};
int gcd(int A,int B){ //必学技能!
if(B == 0) return A;
return gcd(B,A % B);
}
void bfs(){
queue<node>q;
q.push((node){x,y,0});
vis[x][y] = 1;
int nows = a[x][y]; //nows表示目前目标点状态
if(nows == 1){ //这很重要!
cout<<"0";
return;
}
while(!q.empty()){
node tot = q.front();
q.pop();
for(int i = 0; i < 4; i++){
int sx = tot.nowx + dx[i],sy = tot.nowy + dy[i];
if(sx < 1 || sx > n || sy < 1 || sy > m || vis[sx][sy]) continue;
vis[sx][sy] = 1;
q.push((node){sx,sy,tot.now + 1});
nows = gcd(nows,a[sx][sy]); //更新nows
}
if(nows == 1){
cout<<tot.now + 1;
return;
}
}
cout<<"-1";
}
signed main(){
cin>>n>>m;
for(int i = 1; i <= n; i++){ //读入,没啥好说的
for(int j = 1; j <= m; j++){
cin>>a[i][j];
}
}
cin>>x>>y;
bfs();
return 0;
}