Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 6804 | Accepted: 2293 |
Description
Input
Output
Sample Input
2 6 5 ##### #A#A## # # A# #S ## ##### 7 7 ##### #AAA### # A# # S ### # # #AAA### #####
Sample Output
8 11
Source
问题关键就是处理 任意两字母间的最短距离,由于存在了“墙#” ,这个距离不可能单纯地利用坐标加减去计算,必须额外考虑,推荐用BFS(广搜、宽搜),这是本题的唯一难点,因为prim根本直接套用就可以了
求 任意两字母间的最短距离 时不能直接用BFS求,
1、必须先把矩阵中每一个允许通行的格看做一个结点(就是在矩阵内所有非#的格都作为图M的一个顶点),对每一个结点i,分别用BFS求出它到其他所有结点的权值(包括其本身,为0),构造结点图M;
2、然后再加一个判断条件,从图M中抽取以字母为顶点的图,进而构造字母图N
这个判定条件就是当结点图M中的某点j为字母时,把i到j的权值再复制(不是抽离)出来,记录到字母图N的邻接矩阵中
3、剩下的就是对字母图N求最小生成树了
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int INF=0x3f3f3f3f; int col,row,point[120][120]; int n,cnt,ans,map[120][120],dis[120],vis[120]; int dis1[120][120],vis1[60][60]; char str[60][60]; int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; struct node{ int x,y; }; void BFS(int si,int sj){ queue<node> q; while(!q.empty()) q.pop(); memset(dis1,0,sizeof(dis1)); memset(vis1,0,sizeof(vis1)); vis1[si][sj]=1; node cur,next; cur.x=si; cur.y=sj; q.push(cur); int x,y; while(!q.empty()){ cur=q.front(); q.pop(); if(point[cur.x][cur.y]) map[point[si][sj]][point[cur.x][cur.y]]=dis1[cur.x][cur.y]; for(int i=0;i<4;i++){ next.x=x=cur.x+dir[i][0]; next.y=y=cur.y+dir[i][1]; if(x>=1 && x<=row && y>=1 && y<=col && str[x][y]!='#' && !vis1[x][y]){ vis1[x][y]=1; dis1[x][y]=dis1[cur.x][cur.y]+1; q.push(next); } } } } void Prim(){ int i; for(i=1;i<=cnt;i++){ dis[i]=map[1][i]; vis[i]=0; } dis[1]=0; vis[1]=1; int j,k,tmp; for(i=1;i<=cnt;i++){ tmp=INF; for(j=1;j<=cnt;j++) if(!vis[j] && tmp>dis[j]){ tmp=dis[j]; k=j; } if(tmp==INF) break; vis[k]=1; ans+=dis[k]; for(j=1;j<=cnt;j++) if(!vis[j] && dis[j]>map[k][j]) dis[j]=map[k][j]; } } int main(){ freopen("input.txt","r",stdin); int t; scanf("%d",&t); while(t--){ memset(point,0,sizeof(point)); cnt=0; cin>>col>>row; //printf("row=%d col=%d\n",row,col); gets(str[0]); for(int i=1;i<=row;i++){ gets(str[i]+1); //puts(str[i]); //printf("%c\n",str[i][1]); for(int j=1;j<=col;j++) if(str[i][j]=='A' || str[i][j]=='S') point[i][j]=++cnt; } //printf("cnt=%d\n",cnt); for(int i=1;i<=row;i++) for(int j=1;j<=col;j++) if(point[i][j]) BFS(i,j); /* printf("-------------------------\n"); for(int i=1;i<=cnt;i++){ for(int j=1;j<=cnt;j++) printf("%d ",map[i][j]); printf("\n"); } printf("-------------------------\n"); */ ans=0; Prim(); printf("%d\n",ans); } return 0; }