感受到出题人深深的~恶意
这提醒人们以后。。。数字后面要用gets~不要getchar
此外。。不要相信那个100?
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 8524 | Accepted: 2872 |
Description
Input
Output
Sample Input
2 6 5 ##### #A#A## # # A# #S ## ##### 7 7 ##### #AAA### # A# # S ### # # #AAA### #####
Sample Output
8 11
思路: bfs遍历得两点距(这道题数据不大),prim即可
应用时:30min
实际用时:2h
//M: 5056K T:47MS #include<cstdio> #include <cstring> #include <queue> #include <assert.h> using namespace std; char maz[202][202];//迷宫 bool vis[202][202];//用来存储bfs过程中是否遍历以节约时间 int d[201][202][202];//d[aliennum][y][x]从第alinum到坐标y,x的最小步数 int alien[201][2];//记录alien坐标,地球人也是alien之一 int numa;//alien数目 int x,y;//迷宫总长 int sx,sy;//人类起点 int e[202][202];//建图 typedef pair<int,int> P; queue<P> que;//用来存储bfs结果 const int dx[4]={0,0,-1,1}; const int dy[4]={-1,1,0,0}; bool used[101];//用来存储prim过程 void bfs(){ sx=sy=-1; numa=0; memset(vis,0,sizeof(vis)); for(int i=0;i<y;i++){//为了把s点作为起点所以特意寻找,其实不用 for(int j=0;j<x;j++){ if(maz[i][j]=='S'){ sx=j; sy=i; break; } } } assert(sx!=-1&&sy!=-1);//判断有没有找到sxsy,这次用这个发现scanf读迷宫不可 vis[sy][sx]=true;//起始点当然已经走过了 d[0][sy][sx]=0; alien[numa][0]=sy; alien[numa++][1]=sx; que.push(P(sy,sx));//分层bfs while(!que.empty()){ P p=que.front(); que.pop(); for(int i=0;i<4;i++){ int ny=p.first+dy[i]; int nx=p.second+dx[i]; if(nx>=0&&nx<x&&ny>=0&&ny<y&&!vis[ny][nx]&&maz[ny][nx]!='#'){ d[0][ny][nx]=d[0][p.first][p.second]+1; vis[ny][nx]=true; que.push(P(ny,nx)); if(maz[ny][nx]=='A'){//把所有找到的外星人编个号 alien[numa][0]=ny; alien[numa++][1]=nx; } } } } for(int ai=1;ai<numa;ai++){//以各个外星人作为起点开始 memset(vis,0,sizeof(vis)); int ay=alien[ai][0],ax=alien[ai][1];//外星人地址 d[ai][ay][ax]=0; que.push(P(ay,ax)); vis[ay][ax]=true;//起点当然已经遍历 while(!que.empty()){ P p=que.front(); que.pop(); for(int i=0;i<4;i++){ int ny=p.first+dy[i]; int nx=p.second+dx[i]; if(nx>=0&&nx<x&&ny>=0&&ny<y&&!vis[ny][nx]&&maz[ny][nx]!='#'){ d[ai][ny][nx]=d[ai][p.first][p.second]+1; vis[ny][nx]=true; que.push(P(ny,nx));//从这一点出发的状况加入队列 } } } } for(int i=0;i<numa;i++){//取边建图 for(int j=0;j<numa;j++){ int ay1=alien[j][0],ax1=alien[j][1];//所有的其他外星人坐标,自己对自己肯定是0 e[i][j]=d[i][ay1][ax1]; } } } priority_queue <P,vector<P>, greater <P> > pque; int prim(){ memset(used,0,sizeof(used));//多组case所以memset used[0]=true;//alien[0]是人类,不过也无所谓,总之这个点走过了 int unum=1;//这时候已经加入了一个点,就是人类起点,用来存储当前树有多少已加入节点 for(int i=1;i<numa;i++){ pque.push(P(e[0][i],i));//把到当前树的所有边都加入以找到最小边,这条边所连的那个点进树没有更短的路径了,因为是树所以这步贪心只会优化结果不会丢失结果 } int ans=0; while(unum<numa){ int t=pque.top().second; int td=pque.top().first; pque.pop(); if(used[t])continue; ans+=td; used[t]=true; unum++; for(int i=0;i<numa;i++){ if(!used[i]){ pque.push(P(e[t][i],i));//按边排序 } } } while(!pque.empty())pque.pop();//多组case所以pop,也许直接建立在过程里更好吧 return ans; } int main(){ int t; scanf("%d",&t); while(t--){ scanf("%d%d",&x,&y); gets(maz[0]);//不想再建一个专门接收空格的字符串所以用了maz[0] for(int i=0;i<y;i++){ gets(maz[i]); } bfs();//取点建图 int ans=prim(); printf("%d\n",ans); } }