题目链接
http://codeforces.com/contest/750/problem/D
思路
其实可以直接暴力的,虽然n有30那么大,状态可以达到 230 ,但是每次生成的节点最多向左边扩展5个,因此,其实向左最大扩展150个,向右最多150个,所以格子最大 300∗300 , 然后每个节点最多向8个方向扩展,并且对每个节点可以走的步数( ti )最大为5,于是总得状态为 300∗300∗8∗5 ,于是我们可以直接暴力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;
}