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; }