思路:求启动所有发动机步数,并且从低到高>>>路径固定>>[0][0]到第一个发动机(i=1) , i-1发动机位置到i发动机位置(i !=1)>>每个发动机位置都进行bfs(),并sum+=>>>只要有一个找不到就失败
坑点,做的时候我考虑到万一初始位置0,0为0应不能行走
但数据没有这个,写了交上去反而错
#include<bits/stdc++.h>
using namespace std;
queue<pair< int ,int > >q;
int n,m;//矩阵数值
struct asc{//结构体
int value;
pair<int ,int > xy;
};
bool sz_pd[55][55];
void pd_cz(){
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
sz_pd[i][j]=false;
}
}
}
int sz[55][55];//矩阵
int fx_sz[4][2]={{1,0},{0,1},{-1,0},{0,-1}};//方向数组
bool cmp(asc a,asc b){//根据值来排序
return a.value<b.value;
}
int bfs(int a){//bfs
int step=0;//步数
while(!q.empty()){//当队列不为空时
int q_len=q.size();//确定每一层pop的个数
for(int i=0;i<q_len;i++){
int x,y;
x=q.front().first;y=q.front().second;
q.pop();
if(sz[x][y]==a){
// cout<<"找到了"<<a<<endl;
return step;
}
for(int j=0;j<4;j++){
int tx,ty;
tx=x+fx_sz[j][0];
ty=y+fx_sz[j][1];
if(tx>=0 && ty>=0 && tx<n && ty<m){//不超范围
if(sz[tx][ty]!=0 && !sz_pd[tx][ty]){//不塌方
q.push({tx,ty});
sz_pd[tx][ty]=true;
//测试
// cout<<"bfs压入"<<tx<<' '<<ty<<endl;
}
}
}
}
step++;//一层pop完步数加一
}
return -1;
}
int main(){
while(cin>>n>>m){
int flag=true;//插旗
vector< asc >v;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin>>sz[i][j];
if(sz[i][j]>1)v.push_back( { sz[i][j],{i,j} } );
}
}
// if(sz[0][0]==0){//假设初始地点为塌方则直接返回不能 想多了!!!!!!!
// cout<<"Oops\n";
// continue;
// }
sort(v.begin(),v.end(),cmp); //按照值来排序
int sum=0;
for(int i=0;i<v.size();i++){
pd_cz(); //重置来剪枝
while(!q.empty()){ //清空队列
q.pop();
}
if(i==0){ //第一个行星发动机(最小的)起点从[0][0]开始
q.push({0,0});
sz_pd[0][0]=true; //剪枝
// cout<<"压入 0,0\n";
}else{
q.push({v[i-1].xy.first,v[i-1].xy.second});//第i个起点为上一个行星发动机位置
sz_pd[v[i-1].xy.first][v[i-1].xy.second]=true;
// cout<<"压入"<<v[i-1].xy.first<<" , "<<v[i-1].xy.second<<endl;
}
// cout<<"值为"<<v[i].value<<endl;
int aa=bfs(v[i].value); //返回步数
if(aa>=0){ //找到了加
sum+=aa;
}else{
// cout<<"Oops\n"; //不能找到表示不可能启动所有发动机
flag=false;
break; //直接退出
}
}
if(flag){ //判断
cout<<sum;
}else{
cout<<"Oops";
}
cout<<"\n";
}
return 0;
}