题意:
给一个x*y的网格,x,y<50,要遍历其中的N个点(N<100),重复走过的路不算,问最短多长。
分析:
由于重复走过的路不算所以可以用最小生成树。
然后该题又是基于网格求两点最近距离,用BFS预处理出每个点到其他点的最短距离,注意这里处理要把A和S还有空格都看做可以走的地方都要处理,
这里的距离数组用dis[i][j]表示到这一次定的基准点的最短距离,用到方向数组(我当时傻逼了,把方向数组的第二个维度开成4了。。。)
处理完后要更新最后在Prim里的距离。
总结:
手残的地方见代码部分吧。
这一题有坑。。。要gets()
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<iostream>
using namespace std;
const int Pmaxn=105;
const int Nmaxn=55;
int dir[4][2]={-1,0,0,1,1,0,0,-1}; //第二个维度是2!!!
int map[Nmaxn][Nmaxn];
int dis[Nmaxn][Nmaxn]; //距离,这里的横纵坐标就是网格里面的横纵坐标,因为每一次都是和基准点的距离不代表点和点的距离,开大了memset会T
int v[Nmaxn][Nmaxn]; // map上是否访问过
int ans[Pmaxn][Pmaxn];
char p[Nmaxn];
int x,y; //x-行 y-列
int t;
int cnt;
struct ali
{
int x,y;
}A[Pmaxn];
int st;
queue<ali> q;
void bfs(int start)
{
q.push(A[start]);
/*for(int i=0;i<=x+1;i++)
{
for(int j=0;j<=y+1;j++)
{
v[i][j]=0;
dis[i][j]=0;
}
}*/
memset(dis,0,sizeof(dis));
memset(v,0,sizeof(v));
v[A[start].x][A[start].y]=1;//第一个标记入队的点
while(!q.empty())
{
ali top=q.front();
q.pop();
for(int i=0;i<4;i++)
{
int tx,ty;
tx=top.x+dir[i][0];
ty=top.y+dir[i][1];
if(map[tx][ty]!=1 && !v[tx][ty])
{
dis[tx][ty]=dis[top.x][top.y]+1;
v[tx][ty]=1;
ali newer;
newer.x=tx;
newer.y=ty;
q.push(newer);
}
}
}
for(int i=1;i<cnt;i++)
{
if(dis[A[i].x][A[i].y])//因为这一题保证了每一个点都会到达,但是如果有的点不能到达,因为之前初始化是距离0,这里加判断看能不能到达,不能就是inf
{
ans[start][i]=dis[A[i].x][A[i].y];
}
}
ans[start][start]=0;
}
const int inf=0x3f3f3f3f;
int lowcost[Pmaxn],closest[Pmaxn];
int res=0;
void prim(int s)
{
int midis,mione;
int i,j;
res=0;
for(i=1;i<cnt;i++)
{
lowcost[i]=ans[s][i];
closest[i]=s;
}
//cout<<" cnt= "<<cnt<<endl;
for(i=1;i<cnt;i++)
{
midis=inf;
for(j=1;j<cnt;j++)
{
if(lowcost[j]&&midis>lowcost[j])
{
midis=lowcost[j];
mione=j;
}
}//minone的处理是在一轮循环后找到最大值才定,这里括号加错了。。。找了好久。
res+=lowcost[mione];
//cout<<A[mione].x<<" "<<A[mione].y<<" "<<lowcost[mione]<<endl;
lowcost[mione]=0;//表示已经加入树
for(j=1;j<cnt;j++)
{
if(lowcost[j]>ans[j][mione] && lowcost[j])
{
lowcost[j]=ans[j][mione];
closest[j]=mione;
}
}
}
}
int main()
{
//freopen("in","r",stdin);
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&y,&x);
int i,j;
cnt=1;
memset(ans,0x3f,sizeof(ans));
for(i=0;i<=x+1;i++)
map[i][0]=map[i][y+1]=1;
for(i=0;i<=y+1;i++)
map[0][i]=map[x+1][i]=1;
gets(p);//cout<<p;
for(i=1;i<=x;i++)
{
gets(p);//cout<<p;
for(j=1;j<=y;j++)
{
if(p[j-1]=='S' || p[j-1]=='A')//这里的j要-1
{
if(p[j-1]=='S') st=cnt;
map[i][j]=2;
A[cnt].x=i;
A[cnt].y=j;
cnt++;
}
else if(p[j-1]==' ')
map[i][j]=0;
else if(p[j-1]=='#')
map[i][j]=1;
//printf("map[%d][%d]=%d \n",i,j,map[i][j]);
}
//cout<<endl;
}
/*for(i=0;i<=x+1;i++)
{
for(j=0;j<=y+1;j++)
cout<<map[i][j];
cout<<endl;
}*/
for(i=1;i<cnt;i++)
{
//cout<<i<<endl;
bfs(i);
}
/*for(i=1;i<cnt;i++)
{
for(j=1;j<cnt;j++)
cout<<A[i].x<<" "<<A[i].y<<" "<<A[j].x<<" "<<A[j].y<<" "<<ans[i][j]<<endl;
cout<<endl;
}*/
prim(st);//第一次非常神奇的我居然没有调用这个函数。。。Orz
printf("%d\n",res);
}
return 0;
}