寒假集训 P1161 飞越原野

JSOI2019冬令营,这题只会输出impossible骗10分,如今也算圆了当时的梦吧

读题发现:宽搜。因为要求最短时间,这和宽搜的长处很像,而且又是一个类似走迷宫的题。

标记当前状态:横坐标,纵坐标,目前已用的时间,余下的能量。

宽搜一定要记得判重! 开一个三维数组,定义为每一坐标(横加纵)和余下能量,如果已经出现过这种状态,那么就舍去。

Q:为什么不需要记录时间?A:因为能量不同,最后的总时间就可能不同,与当前的时间无关

搜索时分两步,首先看走路,然后看飞行。

Q:怎么表示飞的距离?A:乘法。

另:STL的queue可能慢一点,但是不需要手动开空间,而这题明显能够看出不同的状态极多,所以使用STL

具体见代码

#include<iostream>
#include<queue>
using namespace std;
int n,m,d;
const int dx[]={0,0,1,-1};
const int dy[]={1,-1,0,0};
//const自动测算大小
struct node{
    int x,y,e,t;
    node(int _x,int _y,int _e,int _t):x(_x),y(_y),e(_e),t(_t){};
    //这样可以直接变为结构体,免得先定义一个然后慢慢赋值
    //具体原理其实我也不太懂,此处看的别人的代码
};
queue<node> q;
char se[107][107];
bool vis[107][107][107];
void bfs(){
    while(!q.empty()){
        node nw=q.front();
        q.pop();//千万记得出队!!!不然卡死,还不知道为什么
        for(int i=0;i<4;++i){//走路
            int nx=nw.x+dx[i];
            int ny=nw.y+dy[i];
            if(nx<1||nx>n||ny<1||ny>m||se[nx][ny]=='L')continue;
            if(vis[nx][ny][nw.e])continue;
            vis[nx][ny][nw.e]=true;
            if(nx==n&&ny==m){cout<<nw.t+1<<endl;return;}
            //因为最后一步没有加进去,所以要+1
            q.push(node(nx,ny,nw.e,nw.t+1));
        }
        for(int i=0;i<4;++i){
            for(int j=2;j<=nw.e;++j){
                int nx=nw.x+dx[i]*j;
                int ny=nw.y+dy[i]*j;
                if(nx<1||nx>n||ny<1||ny>m)break;
                //因为用的能量越大,飞得越远,所以接下来用更多的能量肯定不行了,算是一个小剪枝
                if(se[nx][ny]=='L')continue;
                if(vis[nx][ny][nw.e-j])continue;
                vis[nx][ny][nw.e-j]=true;
                if(nx==n&&ny==m){cout<<nw.t+1<<endl;return;}
                //因为最后一步没有加进去,所以要+1
                q.push(node(nx,ny,nw.e-j,nw.t+1));
            }
        }
    }
    cout<<"impossible"<<endl;//记得输出不可能的情况
    return;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n>>m>>d;
    for(int i=1;i<=n;++i)
    for(int j=1;j<=m;++j)
    cin>>se[i][j];
    q.push(node(1,1,d,0));
    bfs();
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值