题意:
放烟花。
一个烟花从某一起点开始,沿着当前方向移动指定数量的格子之后爆炸分成两部分,分别沿着当前方向的左上和右上方向移动。而每一部分再沿着当前方向移动指定数量的格子之后爆炸分成两部分。如此递归下去直到指定的深度。问最终被至少被烟花的任一部分覆盖一次的格子数量有多少。
输入:深度及每一层的爆炸前的移动距离。
输出:至少被烟花的任一部分覆盖一次的格子数量。
示例:
input1
4
4 2 2 3
output1
39
input2
6
1 1 1 1 1 3
output2
85
input
1
3
output
3
input1图示:
input2图示:
思路:
深搜。
实现:
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 5 int n, a[35], m[305][305], vis[35][305][305][8]; 6 7 int dx[8] = {1, 1, 0, -1, -1, -1, 0, 1}; 8 int dy[8] = {0, -1, -1, -1, 0, 1, 1, 1}; 9 10 void dfs(int cur, int x, int y, int dir) 11 { 12 if (cur == n || vis[cur][x][y][dir]) 13 return; 14 vis[cur][x][y][dir] = m[x][y] = 1; 15 for (int i = 1; i < a[cur]; i++) 16 { 17 x += dx[dir]; 18 y += dy[dir]; 19 m[x][y] = 1; 20 } 21 int nd = (dir + 1) & 7; 22 dfs(cur + 1, x + dx[nd], y + dy[nd], nd); 23 nd = (dir + 7) & 7; 24 dfs(cur + 1, x + dx[nd], y + dy[nd], nd); 25 } 26 27 int main() 28 { 29 cin >> n; 30 for (int i = 0; i < n; i++) 31 { 32 cin >> a[i]; 33 } 34 dfs(0, 150, 150, 4); 35 int cnt = 0; 36 for (int i = 0; i < 305; i++) 37 { 38 for (int j = 0; j < 305; j++) 39 { 40 if (m[i][j]) 41 cnt++; 42 } 43 } 44 cout << cnt << endl; 45 return 0; 46 }
总结:
当m = 2 ^ k时, n % m = n & (m - 1)。