洛谷 P1126 搬运重物

洛谷 P1126 搬运重物

1.题目链接

​ https://www.luogu.com.cn/problem/P1126

2.解题思路

​ 解题思路 这种题一看就是BFS (边权为1的最短路 或者 说 BFS根据时间一步一步走的,当走到那个点的时候一定就是最短路 但这个题目小的细节特别多QAQ )

​ 具体如下

  • 给的 是方格的颜色

  • 我们的方格是从1开始计数的

  • 给定的起点 或者说我们走的点 如果为 ( x , y ) (x,y) (x,y)的话 那么方格对应 的坐标就是 ( x + 1 , y + 1 ) (x+1,y+1) (x+1,y+1) 举个例子 也就是说 如果起点是 ( 7 , 2 ) (7,2) (7,2) 的话 那么对应的方格是第八行的第三个方格

  • 因此 x坐标我们可以看作从0开始到n y坐标我们可以看作从0开始到m 但是0和上界限我们是不可以走的 因为机器人有体积

  • 然后就是关于 障碍物 障碍物给的是方格的颜色 比如方格坐标是 ( 3 , 4 ) (3,4) 34 那么 (2,3),(2,4),(3,3),(3,4)都是不能走的 那么我们给定以一个坐标

  • 对应的 如果我们走的点 给定是 ( x , y ) (x,y) (x,y) 那么 (x+1,y+1) (x+1,y),(x,y+1),(x,y)都是不能走的 这个我们可以这么想 每一个方格的右下角做坐标对应的是我们走的点 比如方格是第八行第三列 那么左上角的坐标对应的是(7,2) 右下角对应 (8,3) 也就是方格的坐标 那么我们对于给定的坐标的话 我们就假设他是 方格的右下角 看看这个方格是不是黑色的具体可以看图

在这里插入图片描述

​ 对于给定的(x,y)我们只需要四个红点不是黑色就行 因为只有这四个点和他有关 (注意 这里 右下角坐标对应我们的方格 )

//答案应该走的路   
// 4个坐标分别为 x,y,方向,时间 
7 2 2 0
7 2 1 1
7 1 1 2
7 1 0 3
4 1 0 4
1 1 0 5
1 1 3 6
1 4 3 7 
1 5 3 8 
1 5 2 9 
2 5 2 10 
2 5 3 11
2 7 3 12

3.代码

ACcoding

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
typedef  long long int LL;
typedef pair<int,pair<int,int> > PII;
typedef pair<int,int> PII1;
int n,m;
const int N=60;
int a[N][N];
//检查周围是否吐了黑色
bool check_direction(int x,int y)
{
    int dx[4]={1,1,0,0};
    int dy[4]={1,0,0,1};
    for(int i=0;i<=3;i++)
    {
        if(a[x+dx[i]][y+dy[i]]==1)
        {
            return 0;
        }


    }
    return 1;


}
// d[N][N][4] 用来在某个位置 面向某个方向  的时间 
LL d[N][N][4];
LL ans=0;
//检查是否已经到了终点 
bool check(PII end)
{
    int x=end.first;
    int y=end.second.first;
    for(int i=0;i<4;i++)
    {
        if(d[x][y][i]!=-1)
        return 1;

    }
 
    return 0;


}
//完成方向字符串到实数的转换  
int exchange(char s)
{   

    if(s=='N')
    return 0;
    if(s=='W')
    return 1;
    if(s=='S')
    return 2;
    if(s=='E')
    return 3;
}
//根据方向  返回我们怎么走 比如 向N方向走 就返回 dx=-1 dy=0;
PII1 exchange_direction(int x)
{
    PII1 temp;
    if(x==0)
    {
        temp.first=-1;
        temp.second=0;
        return temp;
    }
    if(x==1)
    {
        temp.first=0;
        temp.second=-1;
        return temp;

    }
    if(x==2)
    {
        temp.first=1;
        temp.second=0;
        return temp;
    }
    temp.first=0;
    temp.second=1;
    return temp;



}
LL bfs()
{
    memset(d,-1,sizeof(d));
    PII begin;
    cin>>begin.first>>begin.second.first;
    PII end;
    cin>>end.first>>end.second.first;
    char s;
    cin>>s;
    queue<PII > q;
    begin.second.second=exchange(s);
    q.push(begin);
    int direction=exchange(s);
    d[begin.first][begin.second.first][direction]=0;

    while(q.size())
    {
        auto temp=q.front();
        q.pop();
        // x代表当前的横坐标  y代表当前的纵坐标 direction_temp代表当前的方向  
        int x=temp.first;
        int y=temp.second.first;
        int direction_temp=temp.second.second;  
        // cout<<x<<" "<<y<<" "<<direction_temp<<" "<<d[x][y][direction_temp]<<endl;
        int left=(direction_temp+1+4)%4;
        int right=(direction_temp-1+4)%4;
        if(d[x][y][left]==-1)
        {d[x][y][left]=d[x][y][direction_temp]+1;
            q.push({x,{y,left}});
        }
        if(d[x][y][right]==-1)
        {
        d[x][y][right]=d[x][y][direction_temp]+1;
        q.push({x,{y,right}});
        }
        PII1 direction_temp1=exchange_direction(direction_temp);
        for(int i=1;i<=3;i++)
        {
            int dx=direction_temp1.first;
            int dy=direction_temp1.second;
            if(d[x+dx*i][y+dy*i][direction_temp]==-1&&x+dx*i>=1&&y+dy*i>=1&&x+dx*i<n&&y+dy*i<m&&check_direction(x+dx*i,y+dy*i)==1)
            {
                d[x+dx*i][y+dy*i][direction_temp]=d[x][y][direction_temp]+1;
                q.push({x+dx*i,{y+dy*i,direction_temp}});
            }
            if(x+dx*i<1||x+dx*i>=n||y+dy*i<1||y+dy*i>=m||check_direction(x+dx*i,y+dy*i)==0)
                break;
        }
        if(check(end)==1)
        {
            LL ans=1e9;
            for(int i=0;i<=3;i++)
            {
                int x=end.first;
                int y=end.second.first;
                if(d[x][y][i]!=-1)
                ans=min(ans,d[x][y][i]);


            }
            return ans;
        }


    }
    return -1;

    
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cin>>a[i][j];
        }

    }
    
   cout<<bfs();


    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值