Escape HDU - 3533 bfs+预处理

做这题复习了几点

  • bfs 预处理 ,因为判断某一点能不能走 ,需要提前对每个炮台进行预处理
  • visit 数组 刚开始我想我这个 bfs 是从左上角遍历到右下角,不会回头,于是刚开始并不想构造 visit 数组。但是后来发现还是不太好,主要因为这题比较特别,每个状态三个后继转移状态,如下图,如果选择不走,那么接下来就可能会发生同一个状态多次入队的情况。

111
visit 数组也很好开,因为已经具有最大能量值,直接 visit[x][y][k]
三维数组开起来也不大。
但是我做题的时候没想到。

读题的时候比较费劲,我觉得这题题意比较模糊,大概就是

  1. 城堡会以一定的周期和速度向某个固定方向发射子弹。
  2. 城堡可以挡住到达该点的子弹。
  3. 城堡不能走

相当于闪点 在闪亮的时刻是不能走的。

满足如下公式,代表不能走

设某个城堡发射子弹的周期为 T,速度为 v,从起点到当前点的时间为 t, 当前点与城堡的距离是 s
如果满足 s = (t-k*t)*v ,则不能走。

但做这题的时候,我又犯蠢了。
我想用 一维vector 记录某个点所关联的所有子弹,但是我用 x * m+y 来定位某个点,这样会出现 3*4+4 = 4*4 + 0 = 16 两个不同的点,映射到同一个 index ,这样显然错误,于是我修改这个映射
#define mmm = 10005
用 x * mmm+y 来做映射,这样不会出现两个点映射到一个同一个索引的情况,学艺不精啊。

下附代码:

#include<iostream>
#include<queue>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<cmath>
#include<cstdio>
#include<cstring>

using namespace std;


#define mmm 10005
vector< vector<int> > num(1001000);
int m,n;
int maxp;
int k;
int maze[105][105];
char dirs[4]={'N','S','E','W'};
int ddi[4][2] = {{-1,0},{1,0},{0,1},{0,-1}};
bool vis[105][105][1005];



struct cas
{
    int t;
    int v;
    int dir;
    int x;
    int y;
};
cas  castle[105];
int re;

struct point
{
    int x;
    int y;
    int t;
};

queue<point>qu;
int dqu[3][2]={{1,0},{0,1},{0,0}};
void bfs()
{
    memset(vis,0,sizeof(vis));
    point st;
    point f;
    point next;
    st.x=0;
    st.y=0;
    st.t=0;
    while(!qu.empty())qu.pop();
    qu.push(st);
    while(!qu.empty())
    {
        f = qu.front();

       // cout<<"***** "<<f.x<<" "<<f.y<<" "<<f.t<<endl;
        qu.pop();
        if(f.x==m&&f.y==n)
        {
            re = f.t;
            break;
        }
        if(f.t > maxp)break;//如果已经大于能量值 就不用再算了

        //向右走
        //向下走
        //停住不动
        for(int i=0;i<3;i++)
        {

            int px =f.x+dqu[i][0];
            int py =f.y+dqu[i][1];
            if(px<0||py<0||px>m||py>n||maze[px][py]==-1||vis[px][py][f.t+1]==1)continue;
            //判断是否有子弹

            //cout<<"********************* "<<px<<" "<<py<<" "<<f.t+1<<endl;
            int flag=1;
            for(int j=0;j<num[px*mmm+py].size();j++)
            {

                int s = abs(px - castle[num[px*mmm+py][j]].x) + abs(py - castle[num[px*mmm+py][j]].y);
                int a;
                //cout<<"s = "<<s;
                if(s%castle[num[px*mmm+py][j]].v==0)
                {

                  a = s/castle[num[px*mmm+py][j]].v;
                //  cout<<" s/v 整除 "<<a<<endl;
                }
                else continue;  //如果不整除  这个就不用算了

                if((f.t+1)>=a&&(f.t+1 -a)%castle[num[px*mmm+py][j]].t==0) //如果该点有 子弹
                {
                  // cout<<" t- T / a 整除"<<(f.t+1 -a)/castle[num[px*mmm+py][j]].t;
                   flag=0;
                   break;
                }
               // cout<<endl;

            }
             //cout<<endl;
            if(flag==0)
            {
                //cout<<"此处有子弹 "<<endl;
                continue;
            }
            next.t = f.t+1;
            next.x=px;
            next.y=py;
            vis[px][py][f.t+1]=1;
            qu.push(next); //将合格点入栈
        }
    }
    while(!qu.empty())qu.pop();

}
int main()
{
    char tmp;
    int t,v,x,y;

    while(scanf("%d%d%d%d",&m,&n,&k,&maxp)!=EOF)
    {
        for(int i=0;i<=m;i++)
            for(int j=0;j<=n;j++)
            {
                maze[i][j]=0;
            }

        for(int i=0;i<=m;i++)
        for(int j=0;j<=n;j++)
            num[i*mmm+j].clear();


       for(int i=0;i<k;i++)  //输入城堡的信息
       {
           getchar();
           scanf("%c %d %d %d %d",&tmp,&castle[i].t,&castle[i].v,&castle[i].x,&castle[i].y);
           //cout<<tmp<<" "<<castle[i].t<<" "<<castle[i].v<<" "<<castle[i].x<<" "<<castle[i].y<<endl;

           maze[castle[i].x][castle[i].y] =-1;  //城堡标记为不可达



           for(int j=0;j<4;j++)
           {
               if(tmp ==dirs[j])
               {
                   castle[i].dir =j;break;
               }
           } //记录该点的方向

       }


       //预处理
       for(int i=0;i<k;i++)
       {
           //对该点方向上的所有数值  进行更新
           int px = castle[i].x;
           int py = castle[i].y;

           //cout<<"*****"<<px<<" "<<py<<endl;

           while(1)  //获取新点 进行标记
           {
               maze[px][py]=i;
               px += ddi[castle[i].dir][0];
               py += ddi[castle[i].dir][1];

               //cout<<px<<" "<<py<<endl;


               if(px<0||py<0||px>m||py>n)break;

               if(maze[px][py]==-1)break; //如果遇见城堡

              // cout<<"可以 "<<px*mmm+py<<endl;

               num[px*mmm+py].push_back(i);
           }
           maze[castle[i].x][castle[i].y] =-1;
       }

       re=-1;
       bfs();

       if(re==-1)printf("Bad luck!\n");
       else printf("%d\n",re);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/jackcily/article/details/83512117
今日推荐