题目
题意:
有一个烟花,总共有n层,沿着当前方向穿过t[i]个单位长度后爆炸,每一次爆炸都会分成两半,然后方向是与当前发射方向夹角为正负45度,问有多少个格子被至少一个烟花穿过。
1
≤
n
≤
30
,
1
≤
t
i
≤
5
1 ≤ n ≤ 30,1 ≤ t_i ≤ 5
1 ≤ n ≤ 30,1 ≤ ti ≤ 5
分析:
本题的关键点在于烟花最远能到的范围,其实略加分析即可得出。由于ti很小,所以往一个方向飞的最远距离不超过150,所以最多覆盖300*300的矩阵。
有了这一关键点,虽然后面烟花会爆炸成非常多,但是就只有这些格子,所以我们可以暴力搜索。但是同一格子在每个时刻的状态又略有些不同,有8个方向,爆炸的层数和当前轮数飞的距离。所以需要5元组来表示一个格子的状态,vis[x][y][k][l][st]表示在x,y这个格子当前烟花在第k层方向为l并且已经飞了st的长度。由于这些值都不大,这样乘起来在1e7这个量级,并不会超时。
#include <iostream>
#include <map>
using namespace std;
int d[8][2] = {-1,0,-1,1,0,1,1,1,1,0,1,-1,0,-1,-1,-1};
int a[40];
int n;
bool vis[305][305][35][8][6],visx[305][305];
int ans = 0;
void dfs(int x,int y,int k,int l,int st)
{
if( k == n + 1 ) return;
if( vis[x][y][k][l][st] == 1 ) return;
if( visx[x][y] == 0 ) ans ++;
visx[x][y] = 1;
vis[x][y][k][l][st] = 1;
if( st != a[k] ) dfs(x+d[l][0],y+d[l][1],k,l,st+1);
else
{
dfs(x,y,k+1,(l+1)%8,0);
dfs(x,y,k+1,(l-1+8)%8,0);
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
dfs(151,151,1,0,1);
cout << ans << '\n';
return 0;
}