Codeforces Gym 100800J Jelly Raid (暴搜)

题目大意:

就是在60*60的地图上现在又200只小怪兽, 每只小怪兽都是在一个长度不超过7的路线上来回走, 现在要从起点到终点, 路途中和小怪兽在同一排或者同一列中且没有建筑物遮挡, 也就是说每只小怪兽都会影响到上下左右能之间看见的地方, 除了到达终点的同时是能被看见的 情况外, 其他时刻都不能被看见

移动方式为上下左右或者原地不动, 问起点到终点需要的最短时间, 不能到达就impossible


大致思路:

这种题多半考虑暴搜, 现在为了表示状态, 不能存下200只怪兽的状态, 于是考虑到走的路线长度不超过7, 那么每只怪兽的周期是1, 2, 4, 6, 8, 10, 12, 也就是说最小公共周期是240

那么用vis[x][y][t]表示状态就可以了, 表示在周期t时刻在位置x, y的到达状态即可, 状态总数 60*60*240显然是可以接受的


代码如下:

Result  :  Accepted     Memory  :  6960 KB     Time  :  31 ms

/*
 * Author: Gatevin
 * Created Time:  2015/12/6 14:35:58
 * File Name: Yukinoshita_Yukino.cpp
 */
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;

int X, Y;
int sx, sy, ex, ey;
char maz[70][70];
int P;
vector<pair<int, int> > V[210];
bool vis[70][70][240];
bool obunai[70][70][240];//在周期时刻t, 位置x, y是否危险表示obunai[x][y][t]
int step[70][70][240];
int period[210];
//只有1, 2, 3, 4, 5, 6, 7这几种周期, 那么在LCM(1, 2, 4, 6, 8, 10, 12) = 240范围内是一个怪兽所在位置的周期
#define mp make_pair
#define pb push_back
int dx[] = {1, -1, 0, 0};
int dy[] = {0, 0, -1, 1};

void init()
{
    for(int t = 0; t < 240; t++)
        for(int j = 0; j < P; j++)
        {
            int x = V[j][t % period[j]].first;
            int y = V[j][t % period[j]].second;
            for(int k = 0; k < 4; k++)
            {
                int tx = x, ty = y;
                while(tx >= 0 && tx < X && ty >= 0 && ty < Y)
                {
                    if(maz[tx][ty] == '#') break;
                    obunai[tx][ty][t] = 1;
                    tx += dx[k], ty += dy[k];
                }
            }
        }
    return;
}

queue<pair<pair<int, int>, int> > Q;

void bfs()
{
    Q.push(mp(mp(sx, sy), 0));
    vis[sx][sy][0] = 1;
    step[sx][sy][0] = 0;
    while(!Q.empty())
    {
        int nx = Q.front().first.first, ny = Q.front().first.second;
        int nt = Q.front().second;
        Q.pop();
        if(obunai[nx][ny][nt]) continue;
        for(int i = 0; i < 4; i++)
        {
            int tx = nx + dx[i];
            int ty = ny + dy[i];
            int tt = (nt + 1) % 240;
            if(tx < 0 || tx >= X || ty < 0 || ty >= Y || maz[tx][ty] == '#') continue;
            if(!vis[tx][ty][tt])
            {
                Q.push(mp(mp(tx, ty), tt));
                step[tx][ty][tt] = step[nx][ny][nt] + 1;
                vis[tx][ty][tt] = 1;
            }
        }
        int tx = nx;
        int ty = ny;
        int tt = (nt + 1) % 240;
        if(!vis[tx][ty][tt])
        {
            Q.push(mp(mp(tx, ty), tt));
            vis[tx][ty][tt] = 1;
            step[tx][ty][tt] = step[nx][ny][nt] + 1;
        }
    }
    int ans = 1e9;
    for(int t = 0; t < 240; t++)
        if(vis[ex][ey][t])
            ans = min(ans, step[ex][ey][t]);
    if(ans != 1e9)
        printf("%d\n", ans);
    else puts("IMPOSSIBLE");
    return;
}

int main()
{
    scanf("%d %d", &X, &Y);
    scanf("\n(%d %d) (%d %d)", &sx, &sy, &ex, &ey);
    sx--; sy--; ex--; ey--;
    for(int i = 0; i < X; i++)
        scanf("%s", maz[i]);
    scanf("%d", &P);
    for(int i = 0; i < P; i++)
    {
        scanf("%d", &period[i]);
        for(int j = 0; j < period[i]; j++)
        {
            int x, y;
            scanf(" (%d %d)", &x, &y);
            x--, y--;
            V[i].pb(mp(x, y));
        }
        for(int j = period[i] - 2; j > 0; j--)
            V[i].pb(V[i][j]);
        if(period[i] >= 2) period[i] = 2*(period[i] - 2) + 2;
        else period[i] = 1;
    }
    init();
    bfs();
    return 0;
}
/*

5 5
(2 5) (5 3)
.....
.#.#.
.#.#.
....#
.#.##
1
6 (4 2) (4 3) (3 3) (2 3) (1 3) (1 2)

*/


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值