CSP-C 可怕的宇宙射线

题意

一个宇宙射线,每一次能够往发射的方向辐射ai个单位长度,然后进行分裂,分裂的方向为发射的方向 左右45°,然后再进行沿着分裂方向辐射a1个长度, 详细请看样例解析图,计算辐射的区域个数

样例输入
4(分裂次数)
4 2 2 3 (每次分裂辐射的长度)
样例输出
39 (区域个数)

样例解释图
在这里插入图片描述

思路

  • 此题开始想过dfs进行求解,思维格式化,不会弄坐标,然后就不太会做,借鉴了某大佬的博客,茅塞顿开
  • 首先就是设立起始坐标,这个很重要,按照题目的数据范围,最多辐射150个长度,所以可以设为(300,300),然后左右上下都不会为负;
  • 进行深度搜索,从题目分析有八个方向进行分裂,所以设置偏移量dx,dy进行方向的控制,每一个有八个方向。
  • 设置四维数组,前两维是坐标,第三维是第几次分裂,第四维是方向,第三维是为了区别不同分裂次数分裂同一个点,第四维是为了区别同一分裂次数分裂同一个点。初始四维数组为false,分裂之后设置为true;
  • 创建一个二维数组,对每一个没有访问的点标记true,然后结果+1;在分裂方向上循环从近到远进行标记辐射线路,循环的长度为每一次分裂的长度。
  • 刚开始先进行右侧的搜索,然后进行左侧的搜索,左侧和右侧的区别就是dx偏移量相反。
  • 总共具有8个方向,通过循环求余的方法,循环八个方向进行搜索

总结

  • 做的时候实在不会做,只知道应该是dfs或者bfs,然后坐标不会设立,便得了0分。
  • 去看了某大佬的博客思路,发现了解题思路,思路逐渐明确(感谢大佬),之前思维格式化,以为坐标就是定的,但是在解题中,只需要确定一个初始点,通过偏移量进行相邻位置的探索即可。
  • 不管是深度搜索还是广度搜索,相邻位置的整理非常重要,对于这种有多方向,带坐标的,通过dx,dy偏移量实现

代码

#include<iostream>
#include<queue>
using namespace std;
int N;//分裂次数
int N_num = 0;//实时分裂次数
int sum = 0;//被辐射的结点
int dx[] = { 0,1,1,1,0,-1,-1,-1 };  //射线分裂的八个方向,右侧方向
int dy[] = { 1,1,0,-1,-1,-1,0,1 };
int displace[30] = { 0 };//射线分裂的长度
bool split[600][600][30][8];//标记是否被分裂
bool vis[600][600];//标记是否被访问
void dfs_search(int x, int y, int direct, int N_num)
{
	//设置dfs的边界
	if (N_num ==N)
		return;
	if (split[x][y][N_num][direct] == false)  //此中N_num 为了防止不同次的分裂会到一个点,此中的direct为了防止同次分裂为同一个点
	{
		split[x][y][N_num][direct] = true;
		//下一个结点的增幅
		int x1 = dx[direct ];
		int y1 = dy[direct ];
		//开始点的分裂辐射
		for (int i = 1; i <=displace[N_num]; i++) {
			if (!vis[x + x1 * i][y + y1 * i]) {
				vis[x + x1 * i][y + y1 * i] = true;
				sum++;
			}
		}
		int a = x + x1 * displace[N_num];  //下一个应该访问的点x坐标
		int b = y + y1 * displace[N_num];
		int b_direct = (direct + 1)%8;  //右侧
		dfs_search(a, b, b_direct, N_num+1); //右侧分裂
		b_direct = (direct + 7)%8; //左侧
		dfs_search(a, b, b_direct, N_num+1);  //左侧分裂
	}
}
int main()
{	
	cin >> N;
	for (int i = 0; i < N; i++)
		cin >> displace[i];
	dfs_search(300, 300, 0,0);//此处300,300为起点,恰好是个对称中心,(此处借鉴大佬的想法)
	cout << sum << endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值