C-可怕的宇宙射线

题目:

众所周知,瑞神已经达到了CS本科生的天花板,但殊不知天外有天,人外有苟。在浩瀚的宇宙中,存在着一种叫做苟狗的生物,这种生物天生就能达到人类研究生的知识水平,并且天生擅长CSP,甚至有全国第一的水平!但最可怕的是,它可以发出宇宙射线!宇宙射线可以摧毁人的智商,进行降智打击!

宇宙射线会在无限的二维平面上传播(可以看做一个二维网格图),初始方向默认向上。宇宙射线会在发射出一段距离后分裂,向该方向的左右45°方向分裂出两条宇宙射线,同时威力不变!宇宙射线会分裂n 次,每次分裂后会在分裂方向前进 ai个单位长度。

现在瑞神要带着他的小弟们挑战苟狗,但是瑞神不想让自己的智商降到普通本科生那么菜的水平,所以瑞神来请求你帮他计算出共有多少个位置会被"降智打击"。

输入描述:

输入第一行包含一个正整数n(n<=30) ,表示宇宙射线会分裂n次。

第二行包含n个正整数a1,a2…an,第 i个数ai 表示第 i次分裂的宇宙射线会在它原方向上继续走多少个单位长度。

输出描述:

输出一个数 ans,表示有多少个位置会被降智打击。

样例输入:

4
4 2 2 3

样例输出:

39

在这里插入图片描述

题目分析:

该题题意简要的描述为在一个二维网格面上,从一个点,初始方向向上,往该方向的左右45度放射行进ai,求最终经过网格数量。

首先该题的射线次数是以2的n次方增长的,所以考虑dfs递归深度搜索。然后射线很关键的一点在于方向,由于每次往左右45度方向射出,所以共有八个方向。该八个方向的联系可以用一个圈描述。(如下图所示)对于每一个方向,其下一次射线发射的方向为其图中左右的方向,(除了0,7两个点较为特殊外,其余均为k-1,k+1两个方向)比如,初始方向向上,其第二次放射方向分别为左上和右上。对应于代码中就可以用两个常数数组dx,dy分别存储0-7各个方向的x,y变化值。

在这里插入图片描述
该题还有一个关键点在于时空的限制,因为放射是指数级的,所以朴素的dfs很容易超时,在大佬的点拨下,可以在朴素的dfs上进行剪枝,即判断当前的x,y,r,k状态是否到达过,若到达过则说明回到起点,可以结束dfs递归,判断的方式可以是一个三维数组,加上一个一维数组,也可以是一个四维数组,只要能完整判断当前状态即可。

除了以上在实验过程中还遇到了很多问题,列出一两条如下:

  • 在数据结构的选择上,一开始选择的是队列,然后一个二维数组来判断该点(x,y)是否已经到达过,但是在vs编译的过程中,在判断if(!vis[x][y]) -->vis[x][y]=true;会产生写入内存矛盾的编译错误。队列走不下去了,而因为set自带去重功能,所以换成了set,最后ans输出q.size()即为最终的位置数。
  • 一开始我的dfs是这样子的void dfs(int r,int k,int* s,int x,int y);所以即使加上了剪枝还是会报te,把int *s去掉了才可以。

代码:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<iomanip>
#include<set>
using namespace std;
const int maxn=4e2;
int dx[] = { 0,1,1,1,0,-1,-1,-1 };

int dy[] = { 1,1,0,-1,-1,-1,0,1 };

int n; 
set< pair<int,int> > q;
int s[30];
//int mm=maxn/2;
bool vis[maxn][maxn][31][8]={false};

//memset(vis,false,sizeof(vis));
void dfs(int r,int k,int x,int y)//bi是b的索引,fx是方向
{	
	if(r>n)
	{
		return;
	}
	if(vis[x][y][r][k])
	{
		return;
	}	
	vis[x][y][r][k]=true;
	if(k == 0)  
	{
		for(int i=0;i<s[r];i++)
		{
			x+=dx[k];
			y+=dy[k];
			q.insert(pair<int,int>(x,y)) ;
		}
		dfs(r+1,k+7,x,y);
		dfs(r+1,k+1,x,y);
	}
	if(k == 1||k==2||k==3||k==4||k==5||k==6)   
	{
		for(int i=0;i<s[r];i++)
		{
			x+=dx[k];
			y+=dy[k];
			q.insert(pair<int,int>(x,y));
		}
		dfs(r+1,k-1,x,y);
		dfs(r+1,k+1,x,y);
	}
	if(k == 7) 
	{
		for(int i=0;i<s[r];i++)
		{
			x+=dx[k];
			y+=dy[k];
			q.insert(pair<int,int>(x,y));
		}
		dfs(r+1,k-1,x,y);
		dfs(r+1,k-7,x,y);
	}
}

int main()
{
	
	cin>>n;
	//int s[30];
	//int *a=new int[n];
	for(int i=0;i<n;i++)
	{
		cin>>s[i];	
	}
	int m=maxn/2;
	dfs(0,0,m,m);
	int ans=q.size();
	cout<<ans<<endl;
    return 0;
}

发布了15 篇原创文章 · 获赞 0 · 访问量 801

猜你喜欢

转载自blog.csdn.net/qq_43746837/article/details/104887650
C-
今日推荐