「知乎杯」2018 CCF 大學生計算機系統與程序設計競賽 絕地求生(battleground)

 

CSPfinal 2018安全

 

絕地求生

        對於第1個子任務,因爲全部玩家都在安全區內,直接輸出玩家初始生命值便可;spa

        對於第2個和第4個子任務,因爲數據量較小,能夠從玩家開始向安全區作路徑搜索;code

        對於第3個和第5個子任務,因爲數據量較大,能夠從安全區作一次路徑搜索;orm

        每回合開始清除安全區內的障礙物,每回合結束恢復安全區內的障礙物;xml

        玩家不能進入障礙物的方格;blog

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

        也不能穿越兩個斜向相鄰障礙物方格的間隙;ci

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

 

把全部安全區的點放入隊列,bfs,獲得初始點到安全區的最短距離。string

題目保證每一個玩家給出的目標座標必定在安全區域之內。保證在任意回合,對於任意玩家,都存在一條到達本回合目標位置的移動路線

因此本次的最短距離即爲本輪該玩家的扣血量。

 

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\n",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;
}
相關文章
相關標籤/搜索