codeforces 750D New Year and Fireworks【DFS】
题意:烟花绽放时分为n层,每层会前进ti格,当进入下一层是向左右45°分开前进。 问在网格中,有多少网格至少被烟花经过一次?
题解:最多30层,每层最多前进5格,烟花的活动半径最大为150,每一层的方向都可以由上一层决定,所以一定 小于300*300中情况,直接暴力绽放的过程就行了。bfs和dfs都可以做。
dfs:
#include<stdio.h> #include<iostream> #include<math.h> #include<algorithm> #include<string> typedef long long ll; #define MAXN 100000 using namespace std; int n, a[35], m[305][305], vis[35][305][305][8]; //clockwise int dx[8] = { 1, 1, 0, -1, -1, -1, 0, 1 }; int dy[8] = { 0, -1, -1, -1, 0, 1, 1, 1 }; void dfs(int cur, int x, int y, int dir) { if (cur == n || vis[cur][x][y][dir]) return; vis[cur][x][y][dir] = m[x][y] = 1; for (int i = 1; i < a[cur]; i++) { x += dx[dir]; y += dy[dir]; m[x][y] = 1; } int nd = (dir + 1) & 7; dfs(cur + 1, x + dx[nd], y + dy[nd], nd); nd = (dir + 7) & 7; dfs(cur + 1, x + dx[nd], y + dy[nd], nd); } int main() { cin >> n; for (int i = 0; i < n; i++) { cin >> a[i]; } dfs(0, 150, 150, 4); int cnt = 0; for (int i = 0; i < 305; i++) { for (int j = 0; j < 305; j++) { if (m[i][j]) cnt++; } } cout << cnt << endl; return 0; }
bfs:
#include <cstdio> #include <cstring> #include <queue> #include <algorithm> using namespace std; const int maxn = 310; int mark[maxn][maxn][32][6]; int n,a[32],map[maxn][maxn]; int asp[][2]={{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}}; struct node { int x,y,cnt,dir; //cnt:烟花的层数 dir:烟花前进的方向 }temp; void bfs() { queue<node> q; temp.x=150; temp.y=150; temp.cnt=1; temp.dir=0; q.push(temp); mark[150][150][1][0]=1; while(!q.empty()) { temp=q.front(); q.pop(); int nx=temp.x, ny=temp.y, num=temp.cnt, k=temp.dir; for(int i=1;i<=a[num];++i)//当前层走的路径 { nx+=asp[k][0]; ny+=asp[k][1]; map[nx][ny]=1; } if(num!=n) { int kl=(k-1+8)%8, kr=(k+1)%8;//当前烟花炸裂后,分开的两个子烟花前进的方向 temp.x=nx; temp.y=ny; temp.cnt=num+1; if(!mark[nx][ny][num+1][kl])//kl左45° { mark[nx][ny][num+1][kl]=1; temp.dir=kl; q.push(temp); } if(!mark[nx][ny][num+1][kr])//kr右45° { mark[nx][ny][num+1][kr]=1; temp.dir=kr; q.push(temp); } } } int ans=0; for(int i=0;i<=300;++i) for(int j=0;j<=300;++j) if(map[i][j]) ans++; printf("%d\n",ans); } int main() { while(scanf("%d",&n)!=EOF) { memset(map,0,sizeof(map)); memset(mark,0,sizeof(mark)); for(int i=1;i<=n;++i) scanf("%d",&a[i]); bfs(); } return 0; }