Good Bye 2016 - D
题目链接:http://codeforces.com/contest/750/problem/D
题意:新年烟花爆炸后会往两端45°差分裂。分裂完后变成2部分,之后这2部分继续按这种规则分裂。现在给你每一步分裂的个数。有可能几个部分都是分裂到一个位置,这种情况只算一个。问最后分裂完有多少个。
思路:模拟即可。由于n最多30,每次最多分裂5个。所以总体规模不是很大。但是需要记忆化一下防止TLE。G[][]表示被覆盖的格子。vis[k][i][j][d]表示第k次分裂在位置(i,j)方向为d时是否出现过。然后就BFS模拟。把八个方向以时钟方向表示从0~7。方向k每次分裂相当于分裂了两个方向为(k+1)%8和(k-1+8)%8。
注意可能内存会炸,所以用的bool型数组
#define _CRT_SECURE_NO_DEPRECATE #include<iostream> #include<cstring> #include<string> #include<algorithm> #include<stdio.h> #include<queue> #include<vector> #include<stack> #include<map> #include<set> #include<time.h> #include<cmath> using namespace std; typedef long long int LL; const int MAXN = 500 + 10; int t[MAXN]; bool vis[32][MAXN][MAXN][8], G[MAXN][MAXN]; int Dir[8][2] = { 1, 0, 1, 1, 0, 1, -1, 1, -1, 0, -1, -1, 0, -1, 1, -1 }; struct Node{ int x, y; int dir; int step; Node(int _x = 0, int _y = 0, int _dir = 0, int _step = 0) :x(_x), y(_y), dir(_dir), step(_step){}; }; int BFS(int n){ memset(G, 0, sizeof(G)); memset(vis, 0, sizeof(vis)); queue<Node>Q; Q.push(Node(250, 250, 0, 1)); //设起点为250,250 vis[0][250][250][0] = 1; for (int i = 0; i < t[0]; i++){ //预处理第1次 G[250 + i*Dir[4][0]][250 + i*Dir[4][1]] = 1; } while (!Q.empty()) { Node top = Q.front(); Q.pop(); if (top.step >= n){ break; } Node next; int k = (top.dir - 1 + 8) % 8; for (int i = 1; i <= t[top.step]; i++){ G[top.x + i*Dir[k][0]][top.y + i*Dir[k][1]] = 1; } next.x = top.x + t[top.step] * Dir[k][0]; next.y = top.y + t[top.step] * Dir[k][1]; next.step = top.step + 1; next.dir = k; if (!vis[next.step][next.x][next.y][next.dir]){ Q.push(next); vis[next.step][next.x][next.y][next.dir] = 1; } k = (top.dir + 1) % 8; for (int i = 1; i <= t[top.step]; i++){ G[top.x + i*Dir[k][0]][top.y + i*Dir[k][1]] = 1; } next.x = top.x + t[top.step] * Dir[k][0]; next.y = top.y + t[top.step] * Dir[k][1]; next.step = top.step + 1; next.dir = k; if (!vis[next.step][next.x][next.y][next.dir]){ Q.push(next); vis[next.step][next.x][next.y][next.dir] = 1; } } int ans = 0; for (int i = 0; i < MAXN; i++){ for (int j = 0; j < MAXN; j++){ ans += G[i][j]; } } return ans; } int main(){ //#ifdef kirito // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); //#endif // int start = clock(); int n; while (scanf("%d", &n) != EOF){ for (int i = 0; i < n; i++){ scanf("%d", &t[i]); } printf("%d\n", BFS(n)); } //#ifdef LOCAL_TIME // cout << "[Finished in " << clock() - start << " ms]" << endl; //#endif return 0; }