D. New Year and Fireworks(搜索+记忆化剪枝)

题目

题意:

    有一个烟花,总共有n层,沿着当前方向穿过t[i]个单位长度后爆炸,每一次爆炸都会分成两半,然后方向是与当前发射方向夹角为正负45度,问有多少个格子被至少一个烟花穿过。
     1   ≤   n   ≤   30 , 1   ≤   t i   ≤   5 1 ≤ n ≤ 30,1 ≤ t_i ≤ 5 1n301ti5

分析:

    本题的关键点在于烟花最远能到的范围,其实略加分析即可得出。由于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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值