题意:
宇宙射线会在无限的二维平面上传播(可以看做一个二维网格图),初始方向默认向上。宇宙射线会在发射出一段距离后分裂,向该方向的左右45度方向分裂出两条宇宙射线,同时威力不变。宇宙射线会分裂n次(n<=30),每次分裂后会在分裂方向上前进ai个单位长度(ai<=5)。请输出有多少个位置会被宇宙射线影响到。
思路:
整体思路为dfs剪枝。
首先二维平面使用pointpm类型,记录是否标记与这个坐标经过的射线。射线使用int l[8][31]来记录,第一维为方向(0至7为顺时针的上、右上……),第二维为第几次分裂,内容为分裂长度。
坐标类型为point,包含坐标x,y与方向fx。
接下来是dfs:若是最后一次分裂,只需要将其前进ai格;否则,应先前进ai格,然后分裂出两条射线,然后判断分裂出的射线是否应剪枝,不剪枝则对射线进行dfs。
前进函数应把射线前进ai格,同时在地图上把射线经过的地方进行记录,记录下当前射线的方向以及还要走多长单位距离。
分裂函数,坐标不变,方向更改,根据规定的方向0至7可以轻松算出分裂后的方向。
最后是剪枝部分,需要判断射线当前方向的下一格是否有同一次分裂级数同方向距离减一的标记。若有,则该射线不需要计算分裂,剪枝。
总结:
一道dfs剪枝题,对应CSP T4。 在实验时一个多小时只写了dfs和错误的剪枝,过后才重整思路,写了快一个下午写出来。
剪枝过程:判断射线方向上是否有ai格已经标记(理所当然的WA)->记录射线的方向与长度,没有记录分裂次数(WA,因为可能有两轮射线在同一坐标同方向长度,但后续分裂的前进长度会不同)->记录射线的方向、长度与轮数,但后一次分裂会把轮数覆盖(TLE,剪枝不够多)->最终版本,记录方向、分裂次数与长度。
做题时还纠结了好长时间的内存占用空间,很小气地开了300*300的数组,但其实可以开大亿点点(内存128MB)。
还有计算方向可以使用dx[],dy[]数组来计算,那样更简洁一些,只不过实验时太急,还是用了自己习惯的方式(复制粘贴真香)。
代码:
#include <iostream>
using namespace std;
struct pointpm
{
bool biaoji;
int l[8][31];
pointpm()
{
biaoji=0;
for(int i=0;i<8;i++)
for(int j=0;j<31;j++)
l[i][j]=-1;
}
};
pointpm pingmian[300][300];
int sum=0;
int n;
struct point
{
int x,y;
int fx;
};
void getfx(point &p1,point &p2,point &p3)
{
if(p1.fx==0) p2.fx=1,p3.fx=7;
else if(p1.fx==7) p2.fx=0,p3.fx=6;
else p2.fx=p1.fx+1,p3.fx=p1.fx-1;
}
void qianjin(point &p1,int lun,int l)
{
if(p1.fx==0)
{
for(int i=1;i<=l;i++)
{
if(pingmian[p1.x][p1.y+i].biaoji==0)
{
pingmian[p1.x][p1.y+i].biaoji=1;
sum++;
}
pingmian[p1.x][p1.y+i].l[0][lun]=l-i;
}
p1.x=p1.x,p1.y=p1.y+l;
}
else if(p1.fx==1)
{
for(int i=1;i<=l;i++)
{
if(pingmian[p1.x+i][p1.y+i].biaoji==0)
{
pingmian[p1.x+i][p1.y+i].biaoji=1;
sum++;
}
pingmian[p1.x+i][p1.y+i].l[1][lun]=l-i;
}
p1.x=p1.x+l,p1.y=p1.y+l;
}
else if(p1.fx==2)
{
for(int i=1;i<=l;i++)
{
if(pingmian[p1.x+i][p1.y].biaoji==0)
{
pingmian[p1.x+i][p1.y].biaoji=1;
sum++;
}
pingmian[p1.x+i][p1.y].l[2][lun]=l-i;
}
p1.x=p1.x+l,p1.y=p1.y;
}
else if(p1.fx==3)
{
for(int i=1;i<=l;i++)
{
if(pingmian[p1.x+i][p1.y-i].biaoji==0)
{
pingmian[p1.x+i][p1.y-i].biaoji=1;
sum++;
}
pingmian[p1.x+i][p1.y-i].l[3][lun]=l-i;
}
p1.x=p1.x+l,p1.y=p1.y-l;
}
else if(p1.fx==4)
{
for(int i=1;i<=l;i++)
{
if(pingmian[p1.x][p1.y-i].biaoji==0)
{
pingmian[p1.x][p1.y-i].biaoji=1;
sum++;
}
pingmian[p1.x][p1.y-i].l[4][lun]=l-i;
}
p1.x=p1.x,p1.y=p1.y-l;
}
else if(p1.fx==5)
{
for(int i=1;i<=l;i++)
{
if(pingmian[p1.x-i][p1.y-i].biaoji==0)
{
pingmian[p1.x-i][p1.y-i].biaoji=1;
sum++;
}
pingmian[p1.x-i][p1.y-i].l[5][lun]=l-i;
}
p1.x=p1.x-l,p1.y=p1.y-l;
}
else if(p1.fx==6)
{
for(int i=1;i<=l;i++)
{
if(pingmian[p1.x-i][p1.y].biaoji==0)
{
pingmian[p1.x-i][p1.y].biaoji=1;
sum++;
}
pingmian[p1.x-i][p1.y].l[6][lun]=l-i;
}
p1.x=p1.x-l,p1.y=p1.y;
}
else if(p1.fx==7)
{
for(int i=1;i<=l;i++)
{
if(pingmian[p1.x-i][p1.y+i].biaoji==0)
{
pingmian[p1.x-i][p1.y+i].biaoji=1;
sum++;
}
pingmian[p1.x-i][p1.y+i].l[7][lun]=l-i;
}
p1.x=p1.x-l,p1.y=p1.y+l;
}
}
bool jianzhi(point &p,int lun,int l)
{
if(p.fx==0)
{
if(pingmian[p.x][p.y+1].l[0][lun]==l-1)
return true;
else return false;
}
else if(p.fx==1)
{
if(pingmian[p.x+1][p.y+1].l[1][lun]==l-1)
return true;
else return false;
}
else if(p.fx==2)
{
if(pingmian[p.x+1][p.y].l[2][lun]==l-1)
return true;
else return false;
}
else if(p.fx==3)
{
if(pingmian[p.x+1][p.y-1].l[3][lun]==l-1)
return true;
else return false;
}
else if(p.fx==4)
{
if(pingmian[p.x][p.y-1].l[4][lun]==l-1)
return true;
else return false;
}
else if(p.fx==5)
{
if(pingmian[p.x-1][p.y-1].l[5][lun]==l-1)
return true;
else return false;
}
else if(p.fx==6)
{
if(pingmian[p.x-1][p.y].l[6][lun]==l-1)
return true;
else return false;
}
else if(p.fx==7)
{
if(pingmian[p.x-1][p.y+1].l[7][lun]==l-1)
return true;
else return false;
}
return false;
}
void dfs(point &p1,int i,int *a)
{
if(i==n)
{
qianjin(p1,i,a[i]);
return;
}
qianjin(p1,i,a[i]);
point p2,p3;
p2.x=p1.x,p2.y=p1.y,p3.x=p1.x,p3.y=p1.y;
getfx(p1,p2,p3);
if(!jianzhi(p2,i+1,a[i+1]))
dfs(p2,i+1,a);
if(!jianzhi(p3,i+1,a[i+1]))
dfs(p3,i+1,a);
}
int main()
{
cin>>n;
int *a=new int [n+1];
for(int i=1;i<=n;i++)
cin>>a[i];
point p;
p.x=150,p.y=150,p.fx=0;
dfs(p,1,a);
cout<<sum<<endl;
return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)