话不多说,直接看题:
相当于找一个点使它到3个国家的距离和min,显然,我们不可以枚举点,但是,我们可以对这3个国家分别bfs,然后枚举相加即可。
下面是AC代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m,v1[1005][1005],v2[1005][1005],v3[1005][1005],mm,mmm,x1,yr,x2,y2,x3,y3,min1=10000000;
char a[1005][1005],q;
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
struct node{int x,y,t;
};
deque<node> qq;
void bfs(int num,int v[][1005],int x,int y){while(!qq.empty()) qq.pop_front();qq.push_back({x,y,0});while(!qq.empty()){node ss=qq.front();qq.pop_front();if(v[ss.x][ss.y]!=-1) continue;v[ss.x][ss.y]=ss.t;for(int i=0;i<4;i++){int xx=ss.x+dir[i][0];int yy=ss.y+dir[i][1];if(xx<=0||xx>n||yy<=0||yy>m) continue;if(a[xx][yy]=='#') continue;if(v[xx][yy]!=-1) continue;if((a[xx][yy]-'0'>=1)&&(a[xx][yy]-'0'<=3)) qq.push_front({xx,yy,ss.t});else qq.push_back({xx,yy,ss.t+1});}}
}
signed main(){memset(v1,-1,sizeof(v1));memset(v2,-1,sizeof(v2));memset(v3,-1,sizeof(v3));cin>>n>>m;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){cin>>q;if(q=='1'){x1=i;yr=j;}if(q=='2'){x2=i;y2=j;}if(q=='3'){x3=i;y3=j;}a[i][j]=q;}}bfs(1,v1,x1,yr);bfs(2,v2,x2,y2);bfs(3,v3,x3,y3);for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(v1[i][j]==-1||v2[i][j]==-1||v3[i][j]==-1) continue;if(a[i][j]=='#') continue;if(a[i][j]=='.'&&min1>v1[i][j]+v2[i][j]+v3[i][j]-2)min1=v1[i][j]+v2[i][j]+v3[i][j]-2;if(a[i][j]!='#'&&min1>v1[i][j]+v2[i][j]+v3[i][j])min1=v1[i][j]+v2[i][j]+v3[i][j];}}if(min1==10000000) cout<<-1;else cout<<min1;}
有几点主意:
1.合并时分类讨论
2.可能存在2,3已经联通,这样的话算不在123位置上的结果就重复了导致结果偏大。
但是总有一个正确的结果可以获得,与是没有必要判断。
接题:
显然,我们最多可以通过abs(n-m)次转化,然后当数大于2*n-m就退出。
其实,负数的存在是没必要的;
于是我们可以BFS,复杂度不超过n-m;
class Solution {
public:int solve(int n, int m) {int vis[3001];struct node{int f,cnt;};queue<node> q;q.push({n,0});vis[n]=1;memset(vis,0,sizeof(vis));while(!q.empty()){node ss=q.front();q.pop();if(ss.f==m){return ss.cnt;}if(ss.cnt>abs(n-m)) continue;int xx=ss.f;for(int i=1;i<=3;i++){xx=ss.f;if(i==1) xx++;else if(i==2) xx--;else xx=xx*xx;if(xx<=0) continue;if(xx>m&&(ss.cnt+xx-m)>=abs(m-n)) continue;if(vis[xx]==1) continue;q.push({xx,ss.cnt+1});vis[xx]=1; }}return -1;}
};
接题:
二进制枚举+检验即可,复杂度为(2^n*m)