可怕的宇宙射线-bfs

宇宙射线

问题分析

题干说明是每条射线都会分成两条射线,一条顺时针转45度,一条逆时针转45度。即每条路径都会另分出两条路径,我们要做的是遍历每条路径并计算走的不同位置。使用bfs或dfs都可达成目的,此处采用dfs思想。
首先需要解决不同方向的表示问题,一开始直接枚举了八种方向分别判断,但是写出代码后发现过于冗杂,代码重复度很高,于是总结在不同方向前进时,x,y的变化规律,写入数组。
首先对各个方向进行编号,方便我们通过索引访问,如图
在这里插入图片描述
一开始方向为向上,即0号,他分出的两条路径为1号和7号,求逆时针转45度:(0+1)%8;求顺时针转45度:(0+7)%8。处理其他方向同理。
接着,我们总结在各个方向前进x,y的坐标变化:(数组索引与图中方向编号对应)

int angx[8] = {1, 1, 0,-1,-1,-1, 0, 1};
int angy[8] = {0,-1,-1,-1, 0, 1, 1, 1};

因为本题数据指数级增长,数据量大,一开始没有进行剪枝,一直超时。思考本题中可能的重复数据,因为数据量大,因此完全可能存在一种情况,两个点的坐标相同,前进方向相同,前进步数也相同。
为排除这种情况,采用了四维数组,四个维度分别为:前进步数、x坐标,y坐标,前进方向。初始化为false,在每个起始点首先检查是否为true,如果是,说明重复,直接返回。否则更新为true。
具体代码如下:

代码实现(dfs递归)

#include<stdio.h>
#include<queue>
#include<math.h>
using namespace std;

struct point
{
	int x;
	int y;
};
int angx[8] = {1, 1, 0,-1,-1,-1, 0, 1};
int angy[8] = {0,-1,-1,-1, 0, 1, 1, 1};
int n=0;
int *a;
int r[400][400]={0};
bool vis[31][400][400][8] ={false};
int ans=0;

void radio(int index,point b,int ang)
{
	int sx = b.x;
	int sy = b.y;
	if(index == n) return;	//结束返回条件
	if(vis[index][sx][sy][ang] == true) return;//剪枝
		
	vis[index][sx][sy][ang] = true;
		
	for(int j=0; j<a[index]; j++)
	{
		if(r[sx][sy] == 0)
		{
			r[sx][sy] = 1;
			ans++;
		}
		sx += angx[ang];
		sy += angy[ang];
	}
	sx -= angx[ang];
	sy -= angy[ang];
	
	point s;
	int temp = (ang+1)%8;//逆时针45 
	s.x = sx+angx[temp];
	s.y = sy+angy[temp];
	
	radio(index+1,s,temp);
	
	temp = (ang+7)%8;
	s.x = sx+angx[temp];
	s.y = sy+angy[temp];
	
	radio(index+1,s,temp);
	
}

int main()
{
	
	scanf("%d",&n);
	a = new int[n];
	for(int i=0; i<n; i++)
	    scanf("%d",&a[i]);
	point t;
	t.x=200;
	t.y=200;
	radio(0, t, 0);

	printf("%d\n",ans);
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值