codeforces contest750 New Year and Fireworks

本文解析CodeForces D题“NewYearandFireworks”,通过记忆化搜索算法计算烟花爆炸覆盖的所有网格数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题链接:http://codeforces.com/contest/750/problem/D



D. New Year and Fireworks
time limit per test
2.5 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

One tradition of welcoming the New Year is launching fireworks into the sky. Usually a launched firework flies vertically upward for some period of time, then explodes, splitting into several parts flying in different directions. Sometimes those parts also explode after some period of time, splitting into even more parts, and so on.

Limak, who lives in an infinite grid, has a single firework. The behaviour of the firework is described with a recursion depth n and a duration for each level of recursion t1, t2, ..., tn. Once Limak launches the firework in some cell, the firework starts moving upward. After covering t1 cells (including the starting cell), it explodes and splits into two parts, each moving in the direction changed by 45 degrees (see the pictures below for clarification). So, one part moves in the top-left direction, while the other one moves in the top-right direction. Each part explodes again after covering t2 cells, splitting into two parts moving in directions again changed by 45 degrees. The process continues till the n-th level of recursion, when all 2n - 1 existing parts explode and disappear without creating new parts. After a few levels of recursion, it's possible that some parts will be at the same place and at the same time — it is allowed and such parts do not crash.

Before launching the firework, Limak must make sure that nobody stands in cells which will be visited at least once by the firework. Can you count the number of those cells?

Input

The first line of the input contains a single integer n (1 ≤ n ≤ 30) — the total depth of the recursion.

The second line contains n integers t1, t2, ..., tn (1 ≤ ti ≤ 5). On the i-th level each of 2i - 1 parts will cover ti cells before exploding.

Output

Print one integer, denoting the number of cells which will be visited at least once by any part of the firework.

Examples
input
4
4 2 2 3
output
39
input
6
1 1 1 1 1 3
output
85
input
1
3
output
3
Note

For the first sample, the drawings below show the situation after each level of recursion. Limak launched the firework from the bottom-most red cell. It covered t1 = 4 cells (marked red), exploded and divided into two parts (their further movement is marked green). All explosions are marked with an 'X' character. On the last drawing, there are 4 red, 4 green, 8 orange and 23 pink cells. So, the total number of visited cells is 4 + 4 + 8 + 23 = 39.

For the second sample, the drawings below show the situation after levels 45 and 6. The middle drawing shows directions of all parts that will move in the next level.





题意:已知烟花爆炸的次数N和每次爆炸前进的格数,求烟花在爆炸完成之后占领的全部格子。。

开始时烟花默认向上移动,每次爆炸之后,路径发生改变(以原来方向为准分别向左上和右上45度移动)。


又是一道记忆化搜索,加上方向的处理。


注意:每次移动必须一格一格的移动,保证走过的map所有节点全部标记,而且标记数组dp也必须记录每次前进的个数(开始时我没有记录),这样避免在向同一方向移动到同一格且爆炸的次数相同时看做重复的格子就不再执行了,实际上此时还要看前进格数forward。

题中没有给出范围,但是可以推得:每次移动不超过5格,爆炸不超过30次,所以移动半径在150内。。



代码:

#include <iostream>
#include <cstdio>
#include <cstring>

int a[35];
int map[310][310];
bool dp[310][310][8][5][35];//对于赋值0和1标记时,最好用bool类型(占一个字节),int很容易超内存
int dir[8][2] = { -1, 0, -1, 1, 0, 1, 1, 1, 1, 0, 1, -1, 0, -1, -1, -1 };//向上开始,依次顺时针赋值
int n;

void dfs(int x, int y, int d, int forward, int cnt)//x,y:每次移动之后的坐标,d:每次移动的方向  forward:每次前进的格数  cnt:爆炸的次数
{
	int i;
	if (dp[x][y][d][forward][cnt])
		return;
	if (cnt == n)
		return;
	dp[x][y][d][forward][cnt] = 1;
	map[x][y] = 1;
	if (forward){
		dfs(x + dir[d][0], y + dir[d][1], d, forward - 1, cnt);
	}
	else//forward==0说明本次爆炸的路径已经走完了,又开始下一次爆炸(改变爆炸之后的方向、前进格数和爆炸次数)
	{
		dfs(x, y, (d - 1 + 8) % 8, a[cnt + 1], cnt + 1);
		dfs(x, y, (d + 1) % 8, a[cnt + 1], cnt + 1);
	}
}

int main()
{
	int i, j;
	scanf("%d", &n);
	for (i = 0; i < n; i++)
		scanf("%d", &a[i]);
	dfs(150, 150, 0, a[0] - 1, 0);
	int ans = 0;
	for (i = 0; i <= 300; i++)
		for (j = 0; j <= 300; j++)
			if (map[i][j])
				ans++;
	printf("%d\n", ans);
	return 0;
}


内容概要:本文详细介绍了施耐德M580系列PLC的存储结构、系统硬件架构、上电写入程序及CPU冗余特性。在存储结构方面,涵盖拓扑寻址、Device DDT远程寻址以及寄存器寻址三种方式,详细解释了不同类型的寻址方法及其应用场景。系统硬件架构部分,阐述了最小系统的构建要素,包括CPU、机架和模块的选择与配置,并介绍了常见的系统拓扑结构,如简单的机架间拓扑和远程子站以太网菊花链等。上电写入程序环节,说明了通过USB和以太网两种接口进行程序下载的具体步骤,特别是针对初次下载时IP地址的设置方法。最后,CPU冗余部分重点描述了热备功能的实现机制,包括IP通讯地址配置和热备拓扑结构。 适合人群:从事工业自动化领域工作的技术人员,特别是对PLC编程及系统集成有一定了解的工程师。 使用场景及目标:①帮助工程师理解施耐德M580系列PLC的寻址机制,以便更好地进行模块配置和编程;②指导工程师完成最小系统的搭建,优化系统拓扑结构的设计;③提供详细的上电写入程序指南,确保程序下载顺利进行;④解释CPU冗余的实现方式,提高系统的稳定性和可靠性。 其他说明:文中还涉及一些特殊模块的功能介绍,如定时器事件和Modbus串口通讯模块,这些内容有助于用户深入了解M580系列PLC的高级应用。此外,附录部分提供了远程子站和热备冗余系统的实物图片,便于用户直观理解相关概念。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值