CF750D New Year and Fireworks
传送门
暴力+搜索
手动打表它不香吗【逃~~
首先想到用dfs来遍历烟花分支,用一张表来标记是否经过点,烟花一共有8个方向,而且很容易想到每一个方向过后都只有两个固定的方向可以选择,因此本题可以列举8个方向之后的2种可能来解决。
烟花可能会向四面八方绽开,如果原点为[0,0],坐标可能会有负数,因此我们需要每次在表上操作时对坐标加一个偏移值。因为n<=30,ti<=5,所以最多向一个方向移动150个单位,偏移值为150,标记表开为300*300
需要注意的是,可能有同时在同一位置,同一方向的分支产生,这时需要记忆化,否则会超时QAQ
code:
#includeusing namespace std; const int M=150; int n,a[35],Map[305][305],ans,f[35][305][305][3][3]; void dfs(int step,int x,int y,int p,int q){//当前是第step层,开始坐标为[x,y] //x轴方向为p,y轴方向为q(用-1,1,0表示,x轴和y轴方向是数组存储顺序) if(f[step][x][y][p+1][q+1]) return; f[step][x][y][p+1][q+1]=1;//记忆化剪枝 if(step>n) return;//层数到n+1退出 int len=a[step];//每次走的长度 for(int i=1;i<=len;i++){ x+=p; y+=q;//坐标更新 Map[x][y]=1;//每一步都标记 } int xx,yy;//表示下一步的方向 if(p==-1&&q==0) xx=-1,yy=-1; else if(p==-1&&q==-1) xx=0,yy=-1; else if(p==0&&q==-1) xx=1,yy=-1; else if(p==1&&q==-1) xx=1,yy=0; else if(p==1&&q==0) xx=1,yy=1; else if(p==1&&q==1) xx=0,yy=1; else if(p==0&&q==1) xx=-1,yy=1; else if(p==-1&&q==1) xx=-1,yy=0; dfs(step+1,x,y,xx,yy);//分支1 if(p==-1&&q==0) xx=-1,yy=1; else if(p==-1&&q==1) xx=0,yy=1; else if(p==0&&q==1) xx=1,yy=1; else if(p==1&&q==1) xx=1,yy=0; else if(p==1&&q==0) xx=1,yy=-1; else if(p==1&&q==-1) xx=0,yy=-1; else if(p==0&&q==-1) xx=-1,yy=-1; else if(p==-1&&q==-1) xx=-1,yy=0; dfs(step+1,x,y,xx,yy);//分支2 } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); dfs(1,M,M,-1,0);//注意起始坐标为[M,M] for(int i=0;i<=300;i++) for(int j=0;j<=300;j++) ans+=Map[i][j];//遍历标记表 printf("%d",ans); return 0; }