Description
Input
Output
Sample Input
2 6 5 ##### #A#A## # # A# #S ## ##### 7 7 ##### #AAA### # A# # S ### # # #AAA### #####
Sample Output
8 11
这题A的太困难啦。。昨天开始做,今天早上才A掉。。。
题意:给出一个图,S代表Borg,去抓A。抓到的A就变成Borg(也可以去抓A),然后只有A和S是在一起的时候才可以分开。问最少多少步可以把A全部抓到。
思路:先用最短路求出每两个点之间的距离,用一个dist[x][y]数组保存。x,y分别是该点的序号。
然后再用prime求出最小生成树,即全部抓到最少的步数。因为是求MST,所以A和S是一样的。所以就一同编号了。
#include <iostream> #include <cstdio> #include <algorithm> #include <string> #include <cmath> #include <cstring> #include <queue> #include <set> #include <vector> #include <stack> #include <map> #include <iomanip> #define PI acos(-1.0) #define Max 55 #define inf 1<<28 using namespace std; struct kdq { int x,y; } ; int point[Max][Max],num,numx,numy; char Map[Max][Max],first[Max*Max]; bool visit[Max][Max],v[Max*Max]; int move[Max*Max][Max*Max],n,m,dis[Max*Max],dist[Max*Max][Max*Max],movex[4]= {1,-1,0,0},movey[4]= {0,0,1,-1}; queue<kdq>q; int inmap(int i,int j) { if(i>=1&&j>=0&&i<m&&j<n) return 1; return 0; } void init() { int i,j; for(i=0; i<num+10; i++) { for(j=0; j<num+10; j++) move[i][j]=0,visit[i][j]=0; } } void bfs(int x,int y) { kdq date; date.x=x,date.y=y; init(); visit[x][y]=1; q.push(date); while(!q.empty()) { kdq temp=q.front(); q.pop(); for(int i=0; i<4; i++) { int tx=temp.x+movex[i]; int ty=temp.y+movey[i]; if(inmap(tx,ty)&&Map[tx][ty]!='#'&&!visit[tx][ty]) { move[tx][ty]=move[temp.x][temp.y]+1; visit[tx][ty]=1; if(point[tx][ty])//如果该点是A或者S。即point[temp.x][y=temp.y]!=0。则更新点(x,y)到点(temp.x,temp.y)的距离。 { dist[point[x][y]][point[tx][ty]]=move[tx][ty]; } kdq xx; xx.x=tx; xx.y=ty; q.push(xx); } } } } int prime(int numx,int numy,int num)//以numx,numy为起点,其实任意点都可以。 { int i,j; memset(v,0,sizeof(v)); for(i=1; i<=num; i++) dis[i]=dist[point[numx][numy]][i]; v[point[numx][numy]]=1; int ans=0; for(i=0; i<num-1; i++) { int index=-1; int min=inf; for(j=1; j<=num; j++) { if(min>dis[j]&&!v[j]) min=dis[j],index=j; } if(index==-1) return ans; v[index]=1; ans+=min; for(j=1; j<=num; j++) { if(dis[j]>dist[index][j]&&!v[j]) dis[j]=dist[index][j]; } } return ans; } void read() { int i,j; cin>>n>>m; num=0; gets(first);//万恶的空格。。。 memset(point,0,sizeof(point)); for(i=0; i<m; i++) { gets(Map[i]); } } void solve() { int i,j; for(i=0; i<m; i++) for(j=0; j<n; j++) { if(Map[i][j]=='A'||Map[i][j]=='S') point[i][j]=++num,numx=i,numy=j;//cout<<point[i][j]<<endl;//对每个点A或者S进行编号。 } for(i=0; i<m; i++) { for(j=0; j<n; j++) { if(point[i][j]) bfs(i,j);//求点(i,j)到其他所有点的最短路径。 } } cout<<prime(numx,numy,num)<<endl; } int main() { int i,j,k,l,T; cin>>T; while(T--) { read(); solve(); } return 0; }这道题做完的感受就是,有些细节的地方太粗心了。比如初始化的时候,一开始point[][]没有memset。而且代码写的太凌乱了。这道题最难的地方应该就是给任意两个点求出最短路然后更新。
不过,说实话。。刚才A掉这道题的时候还是很兴奋的。。毕竟A了整整一天半~~~~