标准做法是bfs暴搜
A*当然可过,标准A*寻路。
首先将图转成合适的形式,好看一点。
然后确定起止点。
下面代码未完善,做题时会超时……
不过没错,也离正解不远了。
#include <cstdio>
#include <cstring>
#include <set>
struct point
{
int x,y;
int g,h,f;
bool operator <(const point &s)const
{
return f<s.f;
}
point(){}
};
std::multiset <point> ope;
int a[1001][1001],fax[1001][1001],fay[1001][1001];
bool open[1001][1001],close[1001][1001];
int m,n,cnt;
int hx[]={0,1,0,-1},
hy[]={-1,0,1,0};
point op,ed;
int gujia(point s)
{
int tmp1=s.x-ed.x,tmp2=s.y-ed.y;
if(tmp1<0)tmp1=-tmp1;
if(tmp2<0)tmp2=-tmp2;
return tmp1+tmp2;
}
void search(point st,point fl)
{
st.g=0;
st.h=gujia(st);
st.f=st.g+st.h;
open[st.x][st.y]=1;
ope.insert(st);
// printf("%d\n",st.f);
while(ope.size()!=0)
{
std::multiset <point>::iterator it;
it=ope.begin();
point now=*it;
ope.erase(it);
open[now.x][now.y]=0;
close[now.x][now.y]=1;
if(now.x==fl.x&&now.y==fl.y)
break;
for(int i=0;i<4;i++)
{
point tmp;
tmp.x=now.x+hx[i],tmp.y=now.y+hy[i];
if(a[tmp.x][tmp.y]==-1||close[tmp.x][tmp.y])
continue;
tmp.g=now.g+1;
tmp.h=gujia(tmp);
tmp.f=tmp.g+tmp.h;
if(!open[tmp.x][tmp.y])
{
open[tmp.x][tmp.y]=1;
fax[tmp.x][tmp.y]=now.x,fay[tmp.x][tmp.y]=now.y;
ope.insert(tmp);
}
else
for(std::multiset <point>::iterator j=ope.begin();j!=ope.end();j++)
{
point tp=*j;
if(tp.x==tmp.x && tp.y==tmp.y && tp.g>tmp.g)
{
ope.erase(j);
fax[tmp.x][tmp.y]=now.x,fay[tmp.x][tmp.y]=now.y;
ope.insert(tmp);
break;
}
}
//就是这里,就慢在这里,这个遍历我还没想出方法省掉...
}
}
int j=fl.x,k=fl.y;
int o=j,i=k;
for(;!(j==st.x&&k==st.y);j=fax[o][i],k=fay[o][i])
{
o=j,i=k;
// printf("%d %d\n",o,i);
cnt++;
}
return ;
}
int main()
{
//懒得打了,请脑补
}
/*以下为个人手出的样例
in:
13 5
000000000000000000000000000
0 0 0 00000
000 000 0 0 000 0000000 000
000 0 0 0 000 0 0
000 000 0 0 00000 0 000 0 0
000 0 0 0 0 00000 0 0 0 0
000 0 0 000 00000 0 0 0 0 0
000 0 0 000 000 0 0 0 0
000 0 0 000 0 000 000 0 0 0
0 0 000 0
000000000000000000000000000
out:
32
*/
经过大爷的点拨改进出来一个map版,事实证明这个应该是没错的
#include <cstdio>
#include <cstring>
#include <set>
#include <map>
struct point
{
int x,y;
int g,h,f;
bool operator <(const point &s)const
{
return f<s.f;
}
};
struct zb
{
int x,y;
bool operator <(const zb &s)const
{
return x==s.x?y<s.y:x<s.x;
}
};
std::multiset <point> ope;
std::map <zb,std::multiset <point>::iterator> zbmap;
int a[1010][1010],fax[1010][1010],fay[1010][1010];
bool open[1010][1010],close[1010][1010];
int n,cnt;
int hx[]={0,1,0,-1},
hy[]={-1,0,1,0};
point op,ed;
int gujia(point s)
{
int tmp1=s.x-ed.x,tmp2=s.y-ed.y;
if(tmp1<0)tmp1=-tmp1;
if(tmp2<0)tmp2=-tmp2;
return tmp1+tmp2;
}
void search(point st,point fl)
{
st.g=0;
st.h=gujia(st);
st.f=st.g+st.h;
open[st.x][st.y]=1;
ope.insert(st);
zb po;
po.x=st.x,po.y=st.y;
zbmap[po]=ope.begin();
// printf("%d\n",st.f);
while(ope.size()!=0)
{
std::multiset <point>::iterator it;
it=ope.begin();
point now=*it;
ope.erase(it);
open[now.x][now.y]=0;
close[now.x][now.y]=1;
if(now.x==fl.x&&now.y==fl.y)
break;
for(int i=0;i<4;i++)
{
point tmp;
tmp.x=now.x+hx[i],tmp.y=now.y+hy[i];
if(a[tmp.x][tmp.y]==-1||close[tmp.x][tmp.y]||
tmp.x<0||tmp.x>1000||tmp.y<0||tmp.y>1000)
continue;
zb tp;
tp.x=tmp.x,tp.y=tmp.y;
tmp.g=now.g+1;
tmp.h=gujia(tmp);
tmp.f=tmp.g+tmp.h;
if(!open[tmp.x][tmp.y])
{
open[tmp.x][tmp.y]=1;
fax[tmp.x][tmp.y]=now.x,fay[tmp.x][tmp.y]=now.y;
ope.insert(tmp);
zbmap[tp]=ope.find(tmp);
}
else
{
point s=*zbmap[tp];
if(s.g>tmp.g)
{
ope.erase(zbmap[tp]);
ope.insert(tmp);
zbmap[tp]=ope.find(tmp);
}
}
}
}
int j=fl.x,k=fl.y;
int o=j,i=k;
for(;!(j==st.x&&k==st.y);j=fax[o][i],k=fay[o][i])
{
o=j,i=k;
// printf("!%d %d\n",o,i);
cnt++;
}
return ;
}
int main()
{
memset(a,0,sizeof(a));
scanf("%d%d%d",&op.x,&op.y,&n);
ed.x=500,ed.y=500;
op.x+=500;op.y+=500;
bool flag=1;
for(int i=1;i<=n;i++)
{
int nx,ny;
scanf("%d%d",&nx,&ny);
a[nx+500][ny+500]=-1;
}
search(op,ed);
printf("%d",cnt);
return 0;
}
那么我们来看一下效率
在jdoj上同一道题
可见
A*比一般的bfs快
但空间占用大
可以尝试写IDA*
有效缩小空间