题目三:可怕的宇宙射线
宇宙射线会在无限的二维平面上传播(可以看做一个二维网络图),初始方向默认向上,宇宙射线会在发射一段距离后分裂,向该方向的左右45度方向分裂出两条宇宙射线,同时威力不变!宇宙射线会分裂n次,每次分裂后会在分裂方向前进ai个单位长度。要求计算出共有多少个位置会被打击;
输入描述:
输入第一行包含一个正整数n(n<=30),表示宇宙射线会分裂n次
输入第二行包含n个正整数a1,a2…an,第i个数ai(ai<=5)表示第i次分裂的宇宙射线会在它原方向上继续走多少个单位长度。
输出描述:
输出一个数ans,表示会有多少个位置会被打击;
样例输入:
4
4 2 2 3
样例输出:
39
题目分析:可以首先感觉到,宇宙射线一直在做着重复的事情,并且是一分为二,则在做题目时应当直接反应出利用dfs递归深度搜索即可,当然,利用bfs也可以处理,但是感觉bfs要维护与注意的东西比较多。对于这种dfs递归深搜和一棵二叉树从根遍历一个感觉,主要体会其中的一分为几的分叉思想。当然,简单的dfs深搜肯定是要超时的,因为搜索次数是指数级增长的,但题目中明确提到每次走的距离不超过5,这也就限定了射线所波及到的范围,所以我们可以利用记忆化搜索排查已经做过的工作,在这里我们要利用数组进行记忆,在考试时自己利用了map,但是map是需要维护结构的,故其肯定会造成时间上的浪费。在这里,我们应当认识到,对于记忆化的东西,我们大多是依靠一个数组进行记忆的,这样操作和查询都很简单。同样,在这里我们应当明白,对于一个射线发射,其是由四元构成的。1,横坐标;2,纵坐标;3,方向;4,第几次移动;所以我们在进行记忆时,维护的应当是四维的一个量。另外,在下面的代码中,其中的分叉处理的不够好,造成了很大的冗余,对于此,分叉过程利用一个小循环处理比较好。因为八个方向围成了一个圈,对于圈这种结构,我们实现循环的做法大多是利用指定数组,并加上取模的运算实现。
#include<iostream>
#include<string.h>
using namespace std;
int ans=0;
int cc;
bool mp[310][310];
bool mp2[310][310][7][30];
void func(int x,int y,int* dis,int sty,int n) {
if(n==cc) {
return;
}
if(mp2[x][y][sty][n]==1)
return;
mp2[x][y][sty][n]=1;
if(sty==0) {
for(int i=1; i<=dis[n]; i++) {
if(mp[x+i][y+i]==0) {
ans++;
mp[x+i][y+i]=1;
}
if(mp[x-i][y+i]==0) {
ans++;
mp[x-i][y+i]=1;
}
}
func(x+dis[n],y+dis[n],dis,1,n+1);
func(x-dis[n],y+dis[n],dis,7,n+1);
} else if(sty==1) {
for(int i=1; i<=dis[n]; i++) {
if(mp[x][y+i]==0) {
ans++;
mp[x][y+i]=1;
}
if(mp[x+i][y]==0) {
ans++;
mp[x+i][y]=1;
}
}
func(x,y+dis[n],dis,0,n+1);
func(x+dis[n],y,dis,2,n+1);
} else if(sty==2) {
for(int i=1; i<=dis[n]; i++) {
if(mp[x+i][y+i]==0) {
ans++;
mp[x+i][y+i]=1;
}
if(mp[x+i][y-i]==0) {
ans++;
mp[x+i][y-i]=1;
}
}
func(x+dis[n],y+dis[n],dis,1,n+1);
func(x+dis[n],y-dis[n],dis,3,n+1);
} else if(sty==3) {
for(int i=1; i<=dis[n]; i++) {
if(mp[x+i][y]==0) {
ans++;
mp[x+i][y]=1;
}
if(mp[x][y-i]==0) {
ans++;
mp[x][y-i]=1;
}
}
func(x+dis[n],y,dis,2,n+1);
func(x,y-dis[n],dis,4,n+1);
} else if(sty==4) {
for(int i=1; i<=dis[n]; i++) {
if(mp[x-i][y-i]==0) {
ans++;
mp[x-i][y-i]=1;
}
if(mp[x+i][y-i]==0) {
ans++;
mp[x+i][y-i]=1;
}
}
func(x+dis[n],y-dis[n],dis,3,n+1);
func(x-dis[n],y-dis[n],dis,5,n+1);
} else if(sty==5) {
for(int i=1; i<=dis[n]; i++) {
if(mp[x-i][y]==0) {
ans++;
mp[x-i][y]=1;
}
if(mp[x][y-i]==0) {
ans++;
mp[x][y-i]=1;
}
}
func(x-dis[n],y,dis,6,n+1);
func(x,y-dis[n],dis,4,n+1);
} else if(sty==6) {
for(int i=1; i<=dis[n]; i++) {
if(mp[x-i][y-i]==0) {
ans++;
mp[x-i][y-i]=1;
}
if(mp[x-i][y+i]==0) {
ans++;
mp[x-i][y+i]=1;
}
}
func(x-dis[n],y-dis[n],dis,5,n+1);
func(x-dis[n],y+dis[n],dis,7,n+1);
} else if(sty==7) {
for(int i=1; i<=dis[n]; i++) {
if(mp[x-i][y]==0) {
ans++;
mp[x-i][y]=1;
}
if(mp[x][y+i]==0) {
ans++;
mp[x][y+i]=1;
}
}
func(x-dis[n],y,dis,6,n+1);
func(x,y+dis[n],dis,0,n+1);
}
}
int main() {
memset(mp,0,sizeof(mp));
memset(mp2,0,sizeof(mp2));
cin>>cc;
int* dis=new int[cc];
for(int i=0; i<cc; i++) {
cin>>dis[i];
}
for(int i=0; i<dis[0]; i++) {
mp[150][150+i]=1;
ans++;
}
func(150,150+dis[0]-1,dis,0,1);
cout<<ans<<endl;
}在这里插入代码片