题目如题。题解如题。
由于目标点最多只有4个,先bfs出俩俩最短路(包括起点),再dfs最短路。)0s1A;(当年弱跪杭州之题,现看如此简单)
#include<iostream>
#include<vector>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
struct point
{
int x,y;
int cnt;
};
char a[105][105];
vector<point>po;
int n,m;int k;
int mindis[10][10];
int vis[105][105];
int f[4][2]={0,1,0,-1,1,0,-1,0};
int bfs(int s,int t)
{
memset(vis,0,sizeof(vis));
queue<point>q;
po[s].cnt=0;
po[t].cnt=-1;
q.push(po[s]);
vis[po[s].x][po[s].y]=1;
while(!q.empty())
{
point cur=q.front();
q.pop();
point next;
for(int i=0;i<4;i++)
{
next.x=cur.x+f[i][0];
next.y=cur.y+f[i][1];
if(next.x>=0&&next.x<n&&next.y>=0&&next.y<m&&vis[next.x][next.y]==0&&a[next.x][next.y]!='#')
{
next.cnt=cur.cnt+1;
if(next.x==po[t].x&&next.y==po[t].y)
{
return next.cnt;
}
q.push(next);
vis[next.x][next.y]=1;
}
}
}
return -1;
}
int mins=100000000;
int vis2[10];
void dfs(int u,int lev,int sumdis)
{
if(sumdis>=mins)return ;
if(lev==k)
{
if(sumdis<mins)
{
mins=sumdis;return ;
}
}
for(int i=1;i<=k;i++)
{
if(!vis2[i])
{
vis2[i]=1;
dfs(i,lev+1,sumdis+mindis[u][i]);
vis2[i]=0;
}
}
}
int main()
{
while(~scanf("%d%d",&n,&m)&&(n||m))
{
memset(mindis,0,sizeof(mindis));
mins=100000000;
po.clear();
for(int i=0;i<n;i++)
{
getchar();
for(int j=0;j<m;j++)
{
scanf("%c",&a[i][j]);
if(a[i][j]=='@')
{
point txy;txy.x=i;txy.y=j;
po.push_back(txy);
}
}
}
scanf("%d",&k); int aa,bb;
for(int i=0;i<k;i++)
{
scanf("%d%d",&aa,&bb);
point txy;txy.x=aa-1;txy.y=bb-1;
po.push_back(txy);
}
int mark=1;
for(int i=0;i<k+1;i++)
for(int j=i+1;j<k+1;j++)
{
mindis[j][i]=mindis[i][j]=bfs(i,j);
if(mindis[i][j]==-1)
{
mark=0;break;
}
}
if(mark==0)
{
printf("-1\n");continue;
}
memset(vis2,0,sizeof(vis2));
dfs(0,0,0);
printf("%d\n",mins);
}
}