主要思路:
一道BFS、DFS题
简单分析本题的测试数据可以得到,如果不剪枝,必然超时(毕竟2n 复杂度),所以关键在剪枝,找出那些后续无需进行的“点”;我们不能仅仅靠横纵坐标判断是否到达同一个点,因为对于再次到达的一点来说,有可能方向不同了或者前行的长度不同了,所以以上的情况都是不能剪掉的。
综上所述,同一个“点”的要求如下:
- 横纵坐标相同
- 当前的朝向相同
- 当前分裂的次数相同
显然我们需要一个四维的数组来记录其状态(或者看作是四维空间的一个点),vis[x][y][level][direction]用来记录
B - 咕咕东想吃饭
众所周知,瑞神已经达到了CS本科生的天花板,但殊不知天外有天,
人外有苟,在浩瀚的宇宙中,存在着一种叫做苟狗的生物,
这种生物天生就能达到人类研究生的知识水平,并且天生擅长CSP,
甚至有全国第一的水平!但最可怕的是,它可以发出宇宙射线!
宇宙射线可以摧毁人的智商,进行降智打击!
宇宙射线会在无限的二维平面上传播(可以看做一个二维网格图),
初始方向默认向上。宇宙射线会在发射出一段距离后分裂,
向该方向的左右45°方向分裂出两条宇宙射线,同时威力不变!
宇宙射线会分裂 次,每次分裂后会在分裂方向前进 个单位长度。
现在瑞神要带着他的小弟们挑战苟狗,
但是瑞神不想让自己的智商降到普通本科生 那么菜的水平,
所以瑞神来请求你帮他计算出共有多少个位置会被"降智打击
Input
输入第一行包含一个正整数n,表示宇宙射线会分裂n次
第二行包含n个正整数
第ai个数表示第ai次分裂的宇宙射线会在它原方向上继续走多少个单位长度。
Output
输出一个数 ,表示有多少个位置会被降智打击
Sample Input
4
4 2 2 3
Sample Output
39
A Possible Solution
#include<iostream>
#include<string.h>
#include<set>
using namespace std;
typedef struct tagPoint{
int x,y;
tagPoint(int X,int Y){
x=X;
y=Y;
}
bool operator < (const tagPoint& p) const {
if(x==p.x)return y<p.y;
return x<p.x;
}
}Point;
set<Point> s;
bool vis[306][306][8][31];
int n,arr[31],
dx[]={0,1,1,1,0,-1,-1,-1},
dy[]={1,1,0,-1,-1,-1,0,1};
void solve(int x,int y,int level,int dir){
if(level==n)
return ;
if(vis[x][y][dir][level])
return ;
if(level)
vis[x][y][dir][level]=true;
// cout<<"original : "<<x<<" "<<y<<endl;
for(int i=1;i<=arr[level];i++){
s.insert({x+i*dx[dir],y+i*dy[dir]});
// cout<<x+i*dx[dir]<<" "<<y+i*dy[dir]<<endl;
}
// cout<<endl;
int dir1=dir-1,dir2=dir+1;
if(dir1==-1)dir1=7;
if(dir2==8)dir2=0;
solve(x+dx[dir]*arr[level],y+dy[dir]*arr[level],level+1,dir1);
solve(x+dx[dir]*arr[level],y+dy[dir]*arr[level],level+1,dir2);
}
int main(){
memset(vis,0,sizeof(vis));
cin>>n;
for(int i=0;i<n;i++)
cin>>arr[i];
solve(152,152,0,0);
cout<<s.size()<<endl;
return 0;
}