Buggy Robot Gym - 101291C bfs暴搜(优先队列(负)优化)

https://vjudge.net/problem/Gym-101291C
永远的痛。。。。。
一个月前写这道题,怎么都是wa,今天早上突然想起来这道题,去看了以前的代码,md,一下就找到错误出在哪了。。。。。。
傻逼题。。。。。。。
题意:
给你一个图,给你一个已经写好的操作序列,你可以任意插入 删除修改这个序列。。 问你最少修改几次能使机器人经过终点。
这道题跟uva10047是一毛一样的。 刘汝佳的大白上有这道题。
我们可以以处理好的原操作序列为时间轴,以所用操作数为这个点的权值。
其实本质上就是把每种状态单独看成一个点,因为原操作数最多是50.
图最大也只有50*50 那么只要插入2500次(也许不止,反正可以接受就是了)就铁定能到达终点。
然后就可以跑bfs了。。 新建数组dp[i][j][k] 表示 处理完前i个原操作指令现在到达的点是j k 时的最小花费,用于剪枝。
一个月前我是直接用迪杰特斯拉写的。。。。 脑抽没想到直接跑dij会丢失最优解。。 然后怼了一整天。。。。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fuck(x) cout<<x<<endl
int dp[55][55][55];
class node
{
public:
    int step,ni,nj,w;
    node(int ni,int nj,int step,int w):step(step),w(w),ni(ni),nj(nj) {}
    bool operator < (const node& b) const
    {
        if(w==b.w)
            return step>b.step;// 当添加操作数一样时  优先处理原有指令消耗少的。
        return w>b.w;
    }
    node() {}
};
int n,m;
char maps[55][55];
char zhiling[55];
int diri[5]= {1,-1,0,0,0};
int dirj[5]= {0,0,-1,1,0};
int vis[2500][55][55];
priority_queue<node> PQ;
int dirs(char x)
{
    if(x=='U')
        return 1;
    else if(x=='D')
        return 0;
    else if(x=='L')
        return 2;
    else if(x=='R')
        return 3;
}
bool check(node & next)
{
    if(next.ni<0 || next.nj<0 || next.ni>=n || next.nj>=m||maps[next.ni][next.nj]=='#')
        return false;
    else
    {
        return true;
    }
}
int dij(int si,int sj,int ei,int ej,int len)
{
    node now,next;
    PQ.push(node(si,sj,0,0));
    while(!PQ.empty())
    {
        now=PQ.top();PQ.pop();
        if(now.w<dp[now.step][now.ni][now.nj])
        {
            dp[now.step][now.ni][now.nj]=now.w;
        }
        else continue;
        if(now.step<len)
        {
            int cnt = dirs(zhiling[now.step]);
            next = node(now.ni+diri[cnt],now.nj+dirj[cnt],now.step+1,now.w);
            if(check(next))// 有没有碰壁
                PQ.push(next);
            else
                PQ.push(node(now.ni,now.nj,now.step+1,now.w));// 碰壁之后
            next=node(now.ni,now.nj,now.step+1,now.w+1);//删除这一步,在原地不动
            if(check(next))
            {
                PQ.push(next);
            }
        }
        //cout<<vis[2][0][2]<<endl;
        for(int i=0; i<4; i++)//往四个方向增加一个指令
        {
            next = node(now.ni+diri[i],now.nj+dirj[i],now.step,now.w+1);
            if(check(next))
            {
                PQ.push(next);
            }
        }
    }
}
int main()
{
    cin>>n>>m;
    memset(dp,0x3f,sizeof dp);
    int si,sj,ei,ej;
    for(int i=0; i<n; i++)
        scanf("%s",maps[i]);
    for(int i=0; i<n; i++)
    {
        for(int j = 0; j<m; j++)
        {
            if(maps[i][j] == 'R')
            {
                si=i;
                sj=j;
            }
            else if(maps[i][j] == 'E')
            {
                ei=i;
                ej=j;
            }
        }
    }
    scanf("%s",zhiling);
    int len=strlen(zhiling);
    int ans=0x3f3f3f3f;
    dij(si,sj,ei,ej,len);
    for(int i=0;i<=len;i++)
        ans=min(ans,dp[i][ei][ej]);
    cout<<ans<<endl;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值