USACO 2007 Dec Silver Mud Puddles bfs or A-star

4 篇文章 0 订阅
4 篇文章 0 订阅

标准做法是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*
有效缩小空间

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值