洛谷 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 阅读(...) 评论(...) 编辑 收藏