https://vjudge.net/problem/UVALive-6455
给定一个初始点,问你经过k个点,所用路径最短。
如果不能都经过(有墙有分割),那么就输出-1
思路:广搜查找最短的,后来又发现如果单单从初始点广搜,得到的不一定是最优的方案。所以枚举每个k点作为初始点,然后取最小值。
#include <bits/stdc++.h>
using namespace std;
int fx[2][4]{{1,-1,0,0},{0,0,1,-1}};
const int maxn=105;
struct Node{
int x,y;
int num;//步数
Node(){};
Node(int _a,int _b,int _c){
x=_a;y=_b;num=_c;
};
};
int x;
int y;
char a[maxn][maxn];
bool vis[maxn][maxn];
int m,n;
int k;
int solve(int x1,int y1){
//cout<<"************************"<<endl;
char b[maxn][maxn];
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++)
b[i][j]=a[i][j];
}
queue<Node>q;
q.push(Node(x,y,0));
memset(vis,false,sizeof(vis));
vis[x1][y1]=true;
//cout<<x<<"!!!"<<y<<endl;
int ans=0;
int tim=0;
while(!q.empty()){
Node u=q.front();
q.pop();
for(int i=0;i<4;i++){
int x2=u.x+fx[0][i];
int y2=u.y+fx[1][i];
if(x2<=0||x2>m||y2<=0||y2>n) continue;
if(vis[x2][y2]) continue;
vis[x2][y2]=true;
if(b[x2][y2]=='*'){
b[x2][y2]='.';
while(!q.empty()) q.pop();
memset(vis,false,sizeof(vis));
ans+=u.num+1;
tim++;
q.push(Node(x2,y2,0));
break;
//cout<<q.size()<<"daxiao"<<endl;
}
else if(b[x2][y2]=='.'){
//cout<<"!!"<<endl;
q.push(Node(x2,y2,u.num+1));
}
}
}
if(tim!=k)
return -1;
else
return ans;
}
int main(){
while(~scanf("%d%d",&m,&n)){
if(m==0&&n==0)break;
getchar();
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
scanf("%c",&a[i][j]);
//cout<<a[i][j]<<endl;
if(a[i][j]=='@')
{ x=i;
y=j;
}
}
getchar();
}
memset(vis,false,sizeof(vis));
//cout<<"!!"<<endl;
scanf("%d",&k);
//cout<<k<<endl;
int a1[5],b1[5];
//for(int i=0;i<4;i++)
//cout<<i<<"!!"<<fx[1][i]<<" "<<fx[0][i]<<endl;
for(int i=0;i<k;i++){
scanf("%d%d",&a1[i],&b1[i]);
//cout<<a1<<" ."<<b1<<endl;
a[a1[i]][b1[i]]='*';
}
int min1=-1;
min1=solve(x,y);
for(int i=0;i<k;i++){
int ans=solve(a1[i],b1[i]);
if(ans==-1) {
//cout<<a1[i]<<"!!"<<b1[i]<<endl;
min1=-1;break;}
else
min1=min(min1,ans);
}
printf("%d\n",min1);
}
}