题目大意:
给定一个n*m的方格图,有障碍和K个目标(K<=4),求从某点出发经过所有目标的最短路线
解法:根据只有4个目标,可以先算出每个目标之间的距离,而后从出发点开始进行深搜即可。
对题目中带障碍的静态方格图,A*算法可以非常高效的求出两点之间最短距离。对于估值函数,可以计算较为高效的曼哈顿距离(x坐标之差绝对值加上y坐标之差绝对值之和),可以证明这样的估值函数得到的最终结果必定最优。
#pragma comment(linker, "/STACK:102400000,102400000")
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define CLR(x) memset(x,0,sizeof(x))
#define SETMAX(x) memset(x,0x3f,sizeof(x))
#define SETNO(x) memset(x,-1,sizeof(x))
#define ll long long
#define eps 3e-12
#define pow2(x) ((x)*(x))
#define forto(i,n) for(int i=0;i
#define for1to(i,n) for(int i=1;i<=n;i++)
#define VI vector
using namespace std;
const double PI=acos(-1.0);
#define INF 0x3f3f3f3f
#define NINF 0xbfffffff
using namespace std;
int Map[111][111];
bool visit[111][111];
struct node
{
int x;
int y;
int h;
int g;
int f;
bool operator<(const node& ano) const
{
return f>ano.f;
}
}st;
priority_queue Aq;
int x[5],y[5];
int MinDis[5][5];
int Dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int K;
int n,m;
bool in(int x,int y)
{
if (x<0||y<0||x>=n||y>=m)
return false;
return true;
}
int Astar(int s,int t)
{
CLR(visit);
while(!Aq.empty())
Aq.pop();
st.x=x[s];
st.y=y[s];
st.g=0;
st.h=abs(x[t]-x[s])+abs(y[t]-y[s]);
st.f=st.g+st.h;
visit[x[s]][y[s]]=true;
Aq.push(st);
while(!Aq.empty())
{
st=Aq.top();
Aq.pop();
if (st.x==x[t]&&st.y==y[t])
return st.g;
node st2;
forto(i,4)
{
st2.x=st.x+Dir[i][0];
st2.y=st.y+Dir[i][1];
if (!in(st2.x,st2.y)||Map[st2.x][st2.y]||visit[st2.x][st2.y])
continue;
visit[st2.x][st2.y]=true;
st2.h=abs(x[t]-st2.x)+abs(y[t]-st2.y);
st2.g=st.g+1;
st2.f=st2.h+st2.g;
Aq.push(st2);
}
}
return INF;
}
bool visit2[5];
int result;
void dfs(int prec,int dep,int res)
{
if (dep==K)
{
result=min(result,res);
return;
}
for(int i=1;i<=K;i++)
if (!visit2[i]&&MinDis[prec][i]!=INF)
{
visit2[i]=true;
dfs(i,dep+1,res+MinDis[prec][i]);
visit2[i]=false;
}
}
int main()
{
ios_base::sync_with_stdio(false);
while(cin>>n>>m,n||m)
{
CLR(Map);
forto(i,n)
{
forto(j,m)
{
char t;
cin>>t;
if (t=='#')
Map[i][j]=1;
if (t=='@')
x[0]=i,y[0]=j;
}
}
cin>>K;
for1to(i,K)
{
int tx,ty;
cin>>tx>>ty;
tx--,ty--;
x[i]=tx,y[i]=ty;
}
forto(i,K+1)
for(int j=i+1;j<=K;j++)
MinDis[i][j]=MinDis[j][i]=Astar(i,j);
CLR(visit2);
result=
INF;
visit2[0]=true;
dfs(0,0,0);
visit2[0]=false;
if (result==INF)
cout<<-1<else
cout<return 0;
}