“知乎杯”2018 CCF 大学生计算机系统与程序设计竞赛 绝地求生(battleground)

CSPfinal 2018

 

绝地求生

        对于第1个子任务,由于所有玩家都在安全区内,直接输出玩家初始生命值即可;

        对于第2个和第4个子任务,由于数据量较小,可以从玩家开始向安全区做路径搜索;

        对于第3个和第5个子任务,由于数据量较大,可以从安全区做一次路径搜索;

        每回合开始清除安全区内的障碍物,每回合结束恢复安全区内的障碍物;

        玩家不能进入障碍物的方格;

       if(abstacles[xnew][ynew]==1) return;

        也不能穿越两个斜向相邻障碍物方格的间隙;

       if(abstacles[xold][ynew]&&abstacles[xnew][yold]==1) return;

 

把所有安全区的点放入队列,bfs,得到初始点到安全区的最短距离。

题目保证每个玩家给出的目标坐标一定在安全区域以内。保证在任意回合,对于任意玩家,都存在一条到达本回合目标位置的移动路线

所以本次的最短距离即为本轮该玩家的扣血量。

 

if(!vis[np.x][np.y]&&dat(np)&&(!(i&1)||dat(cp+dir[i-1])||dat(cp+dir[i+1])))

简明而清晰的判断下一个点是否可达,下一个点是否出界

 

 

#include<queue>
#include<cstdio>
#include<cstring>
const int N=400+5;
const int M=1e5+5;
int n,m,ne,f,h,r,hp[M],dis[N][N];
bool data[N][N],vis[N][N];
template <typename T>
inline void read(T &x){
    T f=1;char ch=getchar();x=0;
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    x*=f;
}
struct Point{
    int x,y;
    Point(int _x=0,int _y=0):x(_x),y(_y){}
    inline void Read(){
        read(x);read(y);x++;y++;
    }
    inline int sqr(){
        return x*x+y*y;
    }
    inline Point operator +(const Point &a) const{
        return Point(x+a.x,y+a.y);
    }
    inline Point operator -(const Point &a) const{
        return Point(x-a.x,y-a.y);
    }
}pos[M],cent;
const Point dir[]={
    Point(0, 1), Point(1, 1), Point(1, 0), Point(1, -1),
    Point(0, -1), Point(-1, -1), Point(-1, 0), Point(-1, 1),
    Point(0, 1)
};
inline void Init(){
    read(n);read(m);read(ne);read(f);read(h);
    for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) data[i][j]=1;
    for(int i=1;i<=ne;i++){
        Point p;p.Read();
        data[p.x][p.y]=0;
    }
    for(int i=1;i<=m;i++) pos[i].Read();
    for(int i=1;i<=m;i++) hp[i]=h;
}
inline bool dat(const Point& a){
    return data[a.x][a.y];
}
inline void bfs(){
    std::queue<Point>q;
    memset(vis,0,sizeof vis);
    for(int i=std::max(1,cent.x-r),rx=std::min(n,cent.x+r);i<=rx;i++){
        for(int j=std::max(1,cent.y-r),ry=std::min(n,cent.y+r);j<=ry;j++){
            if((Point(i,j)-cent).sqr()<=r*r){
                q.push(Point(i,j));
                vis[i][j]=1;
                dis[i][j]=0;
            }
        }
    }
    while(!q.empty()){
        Point cp=q.front();q.pop();
        for(int i=0;i<8;i++){
            Point np=cp+dir[i];
            if(!vis[np.x][np.y]&&dat(np)&&(!(i&1)||dat(cp+dir[i-1])||dat(cp+dir[i+1]))){
                vis[np.x][np.y]=1;
                dis[np.x][np.y]=dis[cp.x][cp.y]+1;
                q.push(np);
            }
        }
    }
    for(int i=1;i<=m;i++) hp[i]-=dis[pos[i].x][pos[i].y],pos[i].Read();
}
inline void Solve(){
    while(f--){
        cent.Read();read(r);
        bfs();
    }
    for(int i=1;i<=m;i++) printf("%d
",hp[i]<0?0:hp[i]);
}
int main(){
    freopen("battleground.in","r",stdin); 
    freopen("battleground.out","w",stdout); 
    Init();
    Solve();
    fclose(stdin);fclose(stdout);
    return 0;
}

 

原文地址:https://www.cnblogs.com/shenben/p/11614869.html