bzoj1329: The Morning after Halloween小鬼回家

传送门
根据题目我们推断又是搜索。
但是你单次搜索(16^6*4^5)直接TLE
我们考虑Astar
首先我们预处理处三个终点到其他节点的距离。
然后一个状态个估价函数就是三个节点到三个目标点的距离最大值。
然后我们按照当前步数+估计函数来对状态进行增广
然后你就驶过去了。
辣鸡码农题吃枣药丸

#include<bits/stdc++.h>
using namespace std;
struct pnode{int x,y;};
struct node{
    int ax,ay,bx,by,cx,cy,step,pre;
    node(int Ax,int Ay,int Bx,int By,int Cx,int Cy,int Step,int Pre){
        ax=Ax; ay=Ay; bx=Bx; by=By; cx=Cx; cy=Cy;
        step=Step; pre=Pre;
    }
    bool operator <(const node &a)const{
        return step+pre>a.step+a.pre;
    }
};
char mp[16][16];
int stax,stay,stbx,stby,stcx,stcy;
int edax,eday,edbx,edby,edcx,edcy;
int n,m,k,cnt,oc[5],dis[3][16][16];
int f[16][16][16][16][16][16];
int c[5][2]={{0,1},{0,-1},{1,0},{-1,0},{0,0}};
bool chk(int x,int y){
    return x<0||x>=n||y<0||y>=m||mp[x][y]=='#';
}
void pre(int op){
    queue<pnode> q;
    int x,y;
    if (op==0) x=edax,y=eday;
    if (op==1) x=edbx,y=edby;
    if (op==2) x=edcx,y=edcy;
    dis[op][x][y]=1;
    q.push((pnode){x,y});
    while (!q.empty()){
        pnode tmp=q.front(); q.pop();
        for (int i=0;i<4;i++){
            x=tmp.x+c[i][0],y=tmp.y+c[i][1];
            if (chk(x,y)) continue;
            if (dis[op][x][y]>dis[op][tmp.x][tmp.y]+1){
                dis[op][x][y]=dis[op][tmp.x][tmp.y]+1;
                q.push((pnode){x,y});
            }
        }
    }
}
int h(int ax,int ay,int bx,int by,int cx,int cy){
    return max(dis[0][ax][ay],max(dis[1][bx][by],dis[2][cx][cy]));
}
void Astar(){
    priority_queue<node> q;
    int tax=0,tay=0,tbx=0,tby=0,tcx=0,tcy=0;
    q.push(node(stax,stay,stbx,stby,stcx,stcy,0,h(stax,stay,stbx,stby,stcx,stcy)));
    f[stax][stay][stbx][stby][stcx][stcy]=h(stax,stay,stbx,stby,stcx,stcy);
    while (!q.empty()){
        node tmp=q.top(); q.pop();
        if (tmp.step+tmp.pre>f[tmp.ax][tmp.ay][tmp.bx][tmp.by][tmp.cx][tmp.cy]) continue;
        if (tmp.ax==edax&&tmp.ay==eday&&tmp.bx==edbx&&tmp.by==edby&&tmp.cx==edcx&&tmp.cy==edcy){
            printf("%d\n",tmp.step);
            return;
        }
        for (int i=0;i<=4;i++){
            if (oc[0]){
                tax=tmp.ax+c[i][0];
                tay=tmp.ay+c[i][1];
                if (chk(tax,tay)) continue;
            }
            for (int j=0;j<=4;j++){
                if (oc[1]){
                    tbx=tmp.bx+c[j][0];
                    tby=tmp.by+c[j][1];
                    if (chk(tbx,tby)) continue;
                    if (tax==tbx&&tay==tby) continue;
                    if (tax==tmp.bx&&tay==tmp.by&&tbx==tmp.ax&&tby==tmp.ay) continue;
                }
                for (int k=0;k<=4;k++){
                    if (oc[2]){
                        tcx=tmp.cx+c[k][0];
                        tcy=tmp.cy+c[k][1];
                        if (chk(tcx,tcy)) continue;
                        if ((tax==tcx&&tay==tcy)||(tbx==tcx&&tby==tcy)) continue;
                        if (tax==tmp.cx&&tay==tmp.cy&&tcx==tmp.ax&&tcy==tmp.ay) continue;
                        if (tbx==tmp.cx&&tby==tmp.cy&&tcx==tmp.bx&&tcy==tmp.by) continue;
                    }
                    int t=h(tax,tay,tbx,tby,tcx,tcy);
                    if (tmp.step+1+t<f[tax][tay][tbx][tby][tcx][tcy]){
                        f[tax][tay][tbx][tby][tcx][tcy]=tmp.step+1+t;
                        q.push(node(tax,tay,tbx,tby,tcx,tcy,tmp.step+1,t));
                    }
                }
            }
        }
    }
}
int main(){
    while (scanf("%d%d%d",&m,&n,&k)!=EOF&&n&&m&&k){
        stax=stay=stbx=stby=stcx=stcy=0;
        edax=eday=edbx=edby=edcx=edcy=0;
        memset(mp,0,sizeof(mp));
        memset(oc,0,sizeof(oc));
        memset(f,4,sizeof(f));
        memset(dis,4,sizeof(dis));
        gets(mp[0]);
        for (int i=0;i<n;i++) gets(mp[i]);
        for (int i=0;i<n;i++)
            for (int j=0;j<m;j++){
                if (mp[i][j]=='A') edax=i,eday=j,oc[0]=1;
                if (mp[i][j]=='B') edbx=i,edby=j,oc[1]=1;
                if (mp[i][j]=='C') edcx=i,edcy=j,oc[2]=1;
                if (mp[i][j]=='a') stax=i,stay=j;
                if (mp[i][j]=='b') stbx=i,stby=j;
                if (mp[i][j]=='c') stcx=i,stcy=j;
            }
        for (int i=0;i<3;i++)
            if (oc[i]) pre(i);
            else memset(dis[i],0,sizeof(dis[i]));
        Astar();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值