CF750D New Year and Fireworks

传送门

暴力+搜索

手动打表它不香吗【逃~~


首先想到用dfs来遍历烟花分支,用一张表来标记是否经过点,烟花一共有8个方向,而且很容易想到每一个方向过后都只有两个固定的方向可以选择,因此本题可以列举8个方向之后的2种可能来解决。

烟花可能会向四面八方绽开,如果原点为[0,0],坐标可能会有负数,因此我们需要每次在表上操作时对坐标加一个偏移值。因为n<=30,ti<=5,所以最多向一个方向移动150个单位,偏移值为150,标记表开为300*300

需要注意的是,可能有同时在同一位置,同一方向的分支产生,这时需要记忆化,否则会超时QAQ

code:

#include<bits/stdc++.h>
using 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;
} 
原文地址:https://www.cnblogs.com/shaozhihang/p/12424793.html