POJ 3026
题目大意:
给你一个y*x的字符矩阵,A代表外星人,S代表起点。然后现在有一个团队从起点出发去找外星人。从起点出发或者找到一个外星人,这个团队就可以分成几个小团队然后分头去找。找完所有外星人花费的总距离是所有团队的距离之和。
然后问你,最小总距离话费是多少。(
这道题有个坑,会在输入x,y之后输入一大堆空格。(呵呵...)
比如第二个测试样例:
7 7 ##### #AAA### # A# # S ### # # #AAA### #####从起点出发分成两个团队,一个团队向下找找到棕色的A花费2距离,然后分成两个团队向左找到蓝色的A和向右找到绿色的A,分别花费1距离,所以向下找的团队总花费是2+1+1=4。然后看从起点出发向上找的团队,同样话费4距离找到红黑黄色A,这时在黄色的团队开始去找紫色的A,花费3距离。所以最后总话费为4+4+3=11。
大思路致:
其实想想看,S是可以看成A的,因为它对求最小花费没影响。
因为起点不唯一(从任意的A出发开始找时距离都是从0开始算的),而且求最小总花费,那团队肯定是再找到一个A后,尽可能花费最少的距离去找到另外一个A。这样才能保证,最后的总花费是最少的。
所以我们就可以先将任意两个A(S也看成A)的最短距离求出来,然后找一条合适的路径使得总话费最少,但是要经过所有的A。那么这就是求最小生成树了。至于给了字符矩阵,然后求两个点的最短距离,就用bfs了。。
(刚开始用bfs姿势不对,我用两层for循环去找两个点的最短距离,忘记了一遍bfs就可以跑遍所有图。所以导致超时了。。。。bfs思想贯彻的还是不够深。。。!- -)
AC代码:
#include<stdio.h>
#include<iostream>
#include<map>
#include<string.h>
#include<queue>
using namespace std;
const int inf=99999999;
typedef pair<int,int>Pa;
map<Pa,int>M;
int dis[505][505];
int vis[505][505];
int lowcost[505];
char c[505][505];
int move[4][2]= {{0,1},{0,-1},{1,0},{-1,0}};
int x,y;
struct Node
{
int nx;
int ny;
} node[105];
void bfs(Node st)
{
memset(vis,0,sizeof(vis));
queue<Node>Q;
Q.push(st);
vis[st.nx][st.ny]=1;
while(!Q.empty())
{
Node top=Q.front();
Q.pop();
for(int i=0; i<4; i++)
{
int xx=top.nx+move[i][0];
int yy=top.ny+move[i][1];
if(xx>=1&&xx<=y&&yy>=1&&yy<=x&&c[xx][yy]!='#'&&!vis[xx][yy])
{
vis[xx][yy]=vis[top.nx][top.ny]+1;
if(c[xx][yy]=='A'||c[xx][yy]=='S')
{
dis[M[make_pair(st.nx,st.ny)]][M[make_pair(xx,yy)]]=vis[xx][yy]-1;//起点标记的是一,因为起点不算距离,所以减去一个1
dis[M[make_pair(xx,yy)]][M[make_pair(st.nx,st.ny)]]=vis[xx][yy]-1;//无向
}
Node nnode;
nnode.nx=xx;
nnode.ny=yy;
Q.push(nnode);
}
}
}
return ;
}
int prim(int num)
{
for(int i=2; i<=num; i++)
{
lowcost[i]=dis[1][i];
//cout<<lowcost[i]<<endl;
}
lowcost[1]=0;
int sum=0;
int minl;
int id;
for(int i=2; i<=num; i++)
{
minl=inf;
for(int j=2; j<=num; j++)
{
if(lowcost[j]&&lowcost[j]<minl)
{
minl=lowcost[j];
id=j;
}
}
if(minl==inf)return -1;
sum+=minl;
lowcost[id]=0;
for(int j=2; j<=num; j++)
{
if(lowcost[j]&&lowcost[j]>dis[id][j])
{
lowcost[j]=dis[id][j];
}
}
}
return sum;
}
int main()
{
int t;
while(~scanf("%d",&t))
{
while(t--)
{
M.clear();
int num=1;
Node st;
scanf("%d%d",&x,&y);
char cc=getchar();
while(cc==' ')cc=getchar();//去掉空格
for(int i=1; i<=y; i++)
{
for(int j=1; j<=x; j++)
{
scanf("%c",&c[i][j]);
if(c[i][j]=='A'||c[i][j]=='S')
{
node[num].nx=i;
node[num].ny=j;
M[make_pair(i,j)]=num;
num++;
}
}
if(i!=y)getchar();
}
for(int i=1;i<num;i++)
{
bfs(node[i]);
}
/*for(int i=1;i<=num;i++)
{
for(int j=1;j<=num;j++)
{
cout<<"dis"<<" "<<i<<" "<<j<<" "<<dis[i][j]<<endl;
}
}*/
printf("%d\n",prim(num-1));
}
}
}