Codeforces750D-New Year and Fireworks(bfs)

18 篇文章 0 订阅
5 篇文章 0 订阅

题目链接

http://codeforces.com/contest/750/problem/D

思路

其实可以直接暴力的,虽然n有30那么大,状态可以达到 230 ,但是每次生成的节点最多向左边扩展5个,因此,其实向左最大扩展150个,向右最多150个,所以格子最大 300300 , 然后每个节点最多向8个方向扩展,并且对每个节点可以走的步数( ti )最大为5,于是总得状态为 30030085 ,于是我们可以直接暴力bfs

细节

bfs的时候需要注意的地方:我们用vis数组来保存当前节点坐标为(x, y),扩展方向为t,保存两个值:之前扩展过的最大步数,当前节点是第几次扩展的。
1. 保存当前节点的最大步数,如果我们新的状态能走的步数( ti )更多,我们可以加入队列并且更新vis
2. 如果我们新的状态虽然能够走得步数没有之前多,但是我们新的状态是第a次扩展,vis保存的状态是b次扩展,且 a>b ,那么新的状态可以继续扩展的节点更多,于是也要加入队列并且更新vis

代码

#include <bits/stdc++.h>

using namespace std;

inline int in() {int x; scanf("%d", &x); return x;}

#define pr(x) {cout << #x << ' ' << x << endl;}
#define PII pair<int, int>
#define mp make_pair

const int maxn = 500;
int dx[] = {0, 1, 1, 1, 0, -1, -1, -1};
int dy[] = {1, 1, 0, -1, -1, -1, 0, 1};
int mm = 200;

struct node {
    int x, y, t, s;
};

int t[maxn], n;
PII vis[maxn][maxn][8]; 
int In[maxn][maxn];

void bfs() {
    memset(vis, 0, sizeof(vis));
    queue<node> q;
    q.push((node){mm, mm, 0, 0});
    vis[mm][mm][0].first = t[0];
    vis[mm][mm][0].second = 0;
    while (!q.empty()) {
        node tnode = q.front(); q.pop();
        int newx = tnode.x, newy = tnode.y, step = tnode.s;
        In[tnode.x][tnode.y] = 1;
        for (int i = 0; i < t[step] - 1; i++) {
            newx += dx[tnode.t];
            newy += dy[tnode.t];
            In[newx][newy] = 1;
        }
        if (tnode.s + 1 > n - 1) continue;
        int t1 = (tnode.t + 1) % 8;
        int t2 = (tnode.t + 7) % 8;
        if (vis[newx + dx[t1]][newy + dy[t1]][t1].first < t[tnode.s + 1] || vis[newx + dx[t1]][newy + dy[t1]][t1].second < tnode.s + 1) {
            vis[newx + dx[t1]][newy + dy[t1]][t1].first = t[tnode.s + 1];
            vis[newx + dx[t1]][newy + dy[t1]][t1].second = tnode.s + 1;
            q.push((node){newx + dx[t1], newy + dy[t1], t1, tnode.s + 1});
        }
        if (vis[newx + dx[t2]][newy + dy[t2]][t2].first < t[tnode.s + 1] || vis[newx + dx[t2]][newy + dy[t2]][t2].second < tnode.s + 1) {
            vis[newx + dx[t2]][newy + dy[t2]][t2].first = t[tnode.s + 1];
            vis[newx + dx[t2]][newy + dy[t2]][t2].second = tnode.s + 1;
            q.push((node){newx + dx[t2], newy + dy[t2], t2, tnode.s + 1});
        }
    }
}

int main() {
    n = in();
    int tot = 0;
    for (int i = 0; i < n; i++) t[i] = in();
    bfs();
    for (int i = 0; i < 500; i++) {
        for (int j = 0; j < 500; j++) {
            if (In[i][j]) tot++;
        }
    }
    cout << tot << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值