2019第十届蓝桥杯——I.胖子迷宫

题目意思:给你一个n*m的迷宫,+能走,*障碍物,一个胖子一开始在3,3,体积为5*5

不过胖子走迷宫的目的是为了减肥,给你一个时间k,当到达时间k时,胖子饿瘦了变成3*3,当到达时间2*k时,更瘦了变成1*1

题目要求到达(n-2,m-2)这个点所需的最短时间。

n,m<=300,

 

解决思路,参考hdu1026,bfs+优先队列(这里如果  不直接原地跳跃到k时刻,而是选择time+1呆在原地,那么不用优先队列也可以,优先队列的作用是,每一层扩展开来的结点是会改变时刻的,比如说hdu1026是要在一个节点打怪打几个小时,而普通的队列bfs,以其扩展顺序为时刻,所以按顺序搜索就行了)

注意几点:

1.四个方向的写法:int foot[4][2]={-1,0,1,0,0,-1,0,1};

2.根据当前时间判断胖子大小,然后决定胖子在原地待多少时间(k或者2k)

3.学会了freopen重定向的写法

4.迷宫问题还是在周围附一圈边界写起来方便

5.pre数组主要是为了记录路径方便查看(来自hdu1026),print1函数也是为了打印路径,可忽略。

6.可以尝试que.push({ nex.ti,nex.x,nex.y,nex.da});(与定义int ti,x,y,da;顺序相对应) 的写法

#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>

using namespace std;

char a[310][310];
bool p[310][310];
int n,m,k,dada,num;
int foot[4][2]={-1,0,1,0,0,-1,0,1};

struct node
{
    int ti,x,y,da;
    friend bool operator < (node a,node b)
    {
        return (a.ti>b.ti) || ((a.ti==b.ti)&&(a.da>b.da));
    }
};
priority_queue<node>q;
struct route
{
    int x,y,da,ti;
}pre[310][310][6];

bool pan(int x,int y,int da)
{
    for (int i=x-da;i<=x+da;i++)
        for (int j=y-da;j<=y+da;j++)
        if (a[i][j]=='*') return false;
    return true;
}

int bfs()
{
    node w;
    w.x=3;w.y=3;w.ti=0;w.da=5;
    q.push(w);
    w.x=3;w.y=3;w.ti=k;w.da=3;
    q.push(w);
    w.x=3;w.y=3;w.ti=2*k;w.da=1;
    q.push(w);

    pre[3][3][5].x=-1;pre[3][3][5].y=-1;
    pre[3][3][3].x=-1;pre[3][3][3].y=-1;
    pre[3][3][1].x=-1;pre[3][3][1].y=-1;
    p[3][3]=1;
    w=q.top();
    while (w.x!=n-2 || w.y!=m-2)
    {

        node nex,tem;

        for (int i=0;i<4;i++)
        {
            int x=w.x+foot[i][0],y=w.y+foot[i][1];
            if (pan(x,y,w.da/2) && p[x][y]==0)
            {
                p[x][y]=1;
                nex.x=x;nex.y=y;nex.ti=w.ti+1;

                if (nex.ti>=2*k) nex.da=1;
                else if (nex.ti>=k)
                {
                    nex.da=3;
                    tem.x=x;tem.y=y;tem.ti=2*k;tem.da=1;
                    q.push(tem);
                    pre[tem.x][tem.y][tem.da].x=nex.x;
                    pre[tem.x][tem.y][tem.da].y=nex.y;
                    pre[tem.x][tem.y][tem.da].da=nex.da;
                    pre[tem.x][tem.y][tem.da].ti=nex.ti;
                }
                else
                {
                    nex.da=5;
                    tem.x=x;tem.y=y;tem.ti=2*k;tem.da=1;
                    pre[tem.x][tem.y][tem.da].x=nex.x;
                    pre[tem.x][tem.y][tem.da].y=nex.y;
                    pre[tem.x][tem.y][tem.da].da=nex.da;
                    pre[tem.x][tem.y][tem.da].ti=nex.ti;
                    q.push(tem);
                    tem.x=x;tem.y=y;tem.ti=k;tem.da=3;
                    pre[tem.x][tem.y][tem.da].x=nex.x;
                    pre[tem.x][tem.y][tem.da].y=nex.y;
                    pre[tem.x][tem.y][tem.da].da=nex.da;
                    pre[tem.x][tem.y][tem.da].ti=nex.ti;
                    q.push(tem);
                }
                q.push(nex);
                pre[nex.x][nex.y][nex.da].x=w.x;
                pre[nex.x][nex.y][nex.da].y=w.y;
                pre[nex.x][nex.y][nex.da].da=w.da;
                pre[nex.x][nex.y][nex.da].ti=w.ti;

            }
        }

        q.pop();
        if (q.empty()) break;
        w=q.top();
    }
    dada=w.da;
    if (!q.empty()) return w.ti;
             else   return 0;
}

void print1(int n,int m,int dad,int tt)
{
    int x=pre[n][m][dad].x,y=pre[n][m][dad].y,da=pre[n][m][dad].da,ti=pre[n][m][dad].ti;
    if (x<0) return;
    print1(x,y,da,ti);
    num++;
    printf("%ds:(%d,%d)->(%d,%d),da=%d\n",tt,x,y,n,m,dad);
    /*int z=0;
    if (a[n][m]!='.') z=a[n][m]-'0';
    for (int i=1;i<=z;i++)
    {
        num++;
        printf("%ds:FIGHT AT (%d,%d)\n",num,n-1,m-1);
    }*/
}

int main()
{
    freopen("f1_input.txt","r",stdin); //输入重定向,输入数据将从in.txt文件中读取
    freopen("f1_output.txt","w",stdout); //输出重定向,输出数据将保存在out.txt文件中

    scanf("%d%d%d",&n,&m,&k);getchar();
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=m;j++)
        {
            a[i][j]=getchar();
        }getchar();
    }
    for (int i=0;i<4;i++)
    {
        printf("%d %d\n",foot[i][0],foot[i][1]);
    }
    //return 0;
    printf("%d %d\n",n,m);
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=m;j++)
        {
            printf("%c",a[i][j]);
        }printf("\n");
    }
    for (int i=1;i<=n;i++)
    {
        a[i][0]='*';
        a[i][m+1]='*';
    }
    for (int j=1;j<=m;j++)
    {
        a[0][j]='*';
        a[n+1][j]='*';
    }

    while (!q.empty()) q.pop();
    memset(p,0,sizeof(p));
    memset(pre,0,sizeof(pre));
    int ans=bfs();
    printf("%d\n",ans);
    num=0;
    /*for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=m;j++)
        {
            for (int k=1;k<=5;k=k+2)
            printf("%d %d %d\n",pre[i][j][k].x,pre[i][j][k].y,pre[i][j][k].da);
            printf("j=%d\n",j);
        }printf("\n");
    }*/
    print1(n-2,m-2,dada,ans);
    fclose(stdin);//关闭文件
    fclose(stdout);//关闭文件
    return 0;
}

结果:

参考博客:

https://blog.csdn.net/akunda/article/details/90613048

https://blog.csdn.net/df_cjc/article/details/79110840

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值