【题解】洛谷 P5506 封锁

题目

P5506 封锁

思路

模拟
\(\large\text{读题一定要细心}\)
解释都在代码里。

\(Code\)

#include<bits/stdc++.h>
#define MAXN 101
using namespace std;
int n,t;
struct qwq{
	int dx,dy,dz;
}movebz[5][8];//用于存储f、h对应的正前方
struct info{
	int x,y,z,h,f;
	int atk,def,mat,mdf,hp,fix;
	string cmd;
	bool flag;
}a[MAXN];//存储每一架飞机的信息
inline int read(){
	int x=0;bool f=0;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=!f;c=getchar();}
	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
	return f?-x:x;
}//读优
inline void write(int x){
	if(x<0){
		putchar('-');
		write(-x);
	}else{
		if(x/10) write(x/10);
		putchar(x%10+'0');
	}
}//输优
inline void move(){
	for(int i=1;i<=n;++i){
		if(!a[i].flag) continue;//注意:已经坠毁的飞机就不用移动了。
		a[i].x+=movebz[a[i].h][a[i].f].dx;
		a[i].y+=movebz[a[i].h][a[i].f].dy;
		a[i].z+=movebz[a[i].h][a[i].f].dz;
	}
}//向正前方移动
void work(){//打表,存储f、h对应的正前方
	for(int i=0;i<=7;++i){
		movebz[0][i].dx=0;movebz[0][i].dy=0;movebz[0][i].dz=-1;
		movebz[4][i].dx=0;movebz[4][i].dy=0;movebz[4][i].dz=1;
	}
	movebz[1][0].dx=1;movebz[1][0].dy=0;movebz[1][0].dz=-1;
	movebz[1][1].dx=1;movebz[1][1].dy=1;movebz[1][1].dz=-1;
	movebz[1][2].dx=0;movebz[1][2].dy=1;movebz[1][2].dz=-1;
	movebz[1][3].dx=-1;movebz[1][3].dy=1;movebz[1][3].dz=-1;
	movebz[1][4].dx=-1;movebz[1][4].dy=0;movebz[1][4].dz=-1;
	movebz[1][5].dx=-1;movebz[1][5].dy=-1;movebz[1][5].dz=-1;
	movebz[1][6].dx=0;movebz[1][6].dy=-1;movebz[1][6].dz=-1;
	movebz[1][7].dx=1;movebz[1][7].dy=-1;movebz[1][7].dz=-1;

	movebz[3][0].dx=1;movebz[3][0].dy=0;movebz[3][0].dz=1;
	movebz[3][1].dx=1;movebz[3][1].dy=1;movebz[3][1].dz=1;
	movebz[3][2].dx=0;movebz[3][2].dy=1;movebz[3][2].dz=1;
	movebz[3][3].dx=-1;movebz[3][3].dy=1;movebz[3][3].dz=1;
	movebz[3][4].dx=-1;movebz[3][4].dy=0;movebz[3][4].dz=1;
	movebz[3][5].dx=-1;movebz[3][5].dy=-1;movebz[3][5].dz=1;
	movebz[3][6].dx=0;movebz[3][6].dy=-1;movebz[3][6].dz=1;
	movebz[3][7].dx=1;movebz[3][7].dy=-1;movebz[3][7].dz=1;

	movebz[2][0].dx=1;movebz[2][0].dy=0;movebz[2][0].dz=0;
	movebz[2][1].dx=1;movebz[2][1].dy=1;movebz[2][1].dz=0;
	movebz[2][2].dx=0;movebz[2][2].dy=1;movebz[2][2].dz=0;
	movebz[2][3].dx=-1;movebz[2][3].dy=1;movebz[2][3].dz=0;
	movebz[2][4].dx=-1;movebz[2][4].dy=0;movebz[2][4].dz=0;
	movebz[2][5].dx=-1;movebz[2][5].dy=-1;movebz[2][5].dz=0;
	movebz[2][6].dx=0;movebz[2][6].dy=-1;movebz[2][6].dz=0;
	movebz[2][7].dx=1;movebz[2][7].dy=-1;movebz[2][7].dz=0;
}

int main(){
	work();//预处理movebz数组
	n=read(),t=read();
	string s;
	for(register int i=1;i<=n;++i){
		a[i].x=read(),a[i].y=read();
		a[i].z=read(),a[i].h=read();
		a[i].f=read(),a[i].atk=read();
		a[i].def=read(),a[i].mat=read();
		a[i].mdf=read(),a[i].hp=read();
		a[i].fix=read(),a[i].flag=1;
		cin>>a[i].cmd;
	}//读入好多好恶心~
	for(int i=0;i<t;++i){
		move();//每一次都要移动注意题目中的`先`
		for(int j=1;j<=n;++j){
			if(!a[j].flag||a[j].cmd[i]=='N') continue;//如果已经坠毁或这次无操作就continue
			if(a[j].cmd[i]=='U'&&a[j].h<4) a[j].h++;//向上
			if(a[j].cmd[i]=='D'&&a[j].h>0) a[j].h--;//向下
			if(a[j].cmd[i]=='L'){//向左
				if(a[j].f<7) a[j].f++;
				else a[j].f=0;//认真读题,当f为7时如果在向左就会变为0
			}
			if(a[j].cmd[i]=='R'){
				if(a[j].f>0) a[j].f--;//认真读题
				else a[j].f=7;
			}
			if(a[j].cmd[i]=='F') a[j].hp+=a[j].fix;//修理
			if(a[j].cmd[i]=='A'){//子弹
				int sum=0;//判断向前移动了几次。
				bool f=0;//判断有没有打到一架飞机
				int xx=a[j].x,yy=a[j].y,zz=a[j].z;
				there: xx+=movebz[a[j].h][a[j].f].dx;//每次向前移动
				yy+=movebz[a[j].h][a[j].f].dy;
				zz+=movebz[a[j].h][a[j].f].dz;
				sum++;//移动次数加一
				for(int k=1;k<=n;++k){
					if(!a[k].flag) continue;//如果当前这架飞机坠毁了,就continue
					if(a[k].x==xx&&a[k].y==yy&&a[k].z==zz){//如果当前到达了一架没有坠毁的飞机
						f=1//打到了,qwq;
						int sh=a[j].atk-a[k].def;//计算伤害
						if(sh>0){//抠除血量
							a[k].hp-=sh;
							if(a[k].hp<=0){//因为坠毁的飞机最后输出时血量为0直接改成0
								a[k].hp=0;
								a[k].flag=0;//它坠毁了
							}
						}
						break;//跳出循坏
					}
					if(sum>=400) f=1;//如果进行了8次以上的操作就直接跳出(这是卡测试数据,当时是IOI赛制的比赛)
				}
				if(!f) goto there;//如果还没有打到就再移动
			}
			if(a[j].cmd[i]=='M'){//激光和子弹类似qwq
				int sum=0;//同上
				int xx=a[j].x,yy=a[j].y,zz=a[j].z;
				there2: xx+=movebz[a[j].h][a[j].f].dx;//同上
				yy+=movebz[a[j].h][a[j].f].dy;
				zz+=movebz[a[j].h][a[j].f].dz;
				sum++;//同上
				for(register int k=1;k<=n;++k){
					if(!a[k].flag) continue;//同上
					if(a[k].x==xx&&a[k].y==yy&&a[k].z==zz){
						int sh=a[j].mat-a[k].mdf;//同上
						if(sh>0){//同上
							a[k].hp-=sh;
							if(a[k].hp<=0){
								a[k].flag=0;
								a[k].hp=0;
							}
						}
					}
					if(sum>=400) break;//因为激光是打一行所以不管打没打到继续
				}
				if(sum<400) goto there2;
			}
		}
	}
	for(register int i=1;i<=n;++i){//输出答案qwq
		write(a[i].x);printf(" ");
		write(a[i].y);printf(" ");
		write(a[i].z);printf(" ");
		write(a[i].hp);
		puts("");
	}
	return 0;
}
posted @ 2019-08-14 09:17  yu__xuan  阅读(271)  评论(0编辑  收藏  举报