题解 P5506 【封锁】

· · 题解

//稍作改动 再次提交 望管理大大通过

此文核心收到一位大佬(不知名)启发,因不知为何人,在此感谢

刚看到这道题真的是感觉非常热血沸腾无助!

太弱了看不懂...

后来看了下后面题发现都不会做,就又来看这道题了

其实这道题是一道非常好的模拟????

幸好良心(变态)出题人给了一张表格 因为表里数据比较多,边做边处理太麻烦所以可以先预处理(存数组里)

int s[5][8][3]=
{
    {
        {0,0,-1},{0,0,-1},{0,0,-1},{0,0,-1},{0,0,-1},{0,0,-1},{0,0,-1},{0,0,-1}
    },
    {
        {1,0,-1},{1,1,-1},{0,1,-1},{-1,1,-1},{-1,0,-1},{-1,-1,-1},{0,-1,-1},{1,-1,-1}
    },
    {
        {1,0,0},{1,1,0},{0,1,0},{-1,1,0},{-1,0,0},{-1,-1,0},{0,-1,0},{1,-1,0}
    },
    {
        {1,0,1},{1,1,1},{0,1,1},{-1,1,1},{-1,0,1},{-1,-1,1},{0,-1,1},{1,-1,1}
    },
    {
        {0,0,1},{0,0,1},{0,0,1},{0,0,1},{0,0,1},{0,0,1},{0,0,1},{0,0,1}
    }
};

其中第一维是h,第二维是f,第三维就是x,y,z(方位) 这样便于处理正方向

x+=s[h][f][0];
y+=s[h][f][1];
z+=s[h][f][2];

f:当前水平朝向(范围0-7) h:竖直朝向(范围0-4) (如果f,h对应的是什么都不知道的话,你可以去P1000大佬区了)

题中代码中用到 goto 像我一样的蒟蒻看这里 感谢博主

如有不明白可自行百度

话不多说 上代码

#include<bits/stdc++.h>
using namespace std;                  
int a[205][15];//大佬们用的都是结构体,用结构体确实会方便不少
int vis[105][105][105];
char ch[205][205];
int s[5][8][3]=
{
    {
        {0,0,-1},{0,0,-1},{0,0,-1},{0,0,-1},{0,0,-1},{0,0,-1},{0,0,-1},{0,0,-1}
    },
    {
        {1,0,-1},{1,1,-1},{0,1,-1},{-1,1,-1},{-1,0,-1},{-1,-1,-1},{0,-1,-1},{1,-1,-1}
    },
    {
        {1,0,0},{1,1,0},{0,1,0},{-1,1,0},{-1,0,0},{-1,-1,0},{0,-1,0},{1,-1,0}
    },
    {
        {1,0,1},{1,1,1},{0,1,1},{-1,1,1},{-1,0,1},{-1,-1,1},{0,-1,1},{1,-1,1}
    },
    {
        {0,0,1},{0,0,1},{0,0,1},{0,0,1},{0,0,1},{0,0,1},{0,0,1},{0,0,1}
    }
};
int main(){
    int n,t;
    cin>>n>>t;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=11;j++)
          cin>>a[i][j];
        cin>>ch[i];
        a[i][12]=1;
//a[i][1~11]分别对应题中的各个参量
//a[i][12] 表示这架飞机是否死亡 1为活着 0为死亡
    }
    for(int k=0;k<t;k++){
      for(int i=1;i<=n;i++)
      {
        a[i][1]+=s[a[i][4]][a[i][5]][0];
        a[i][2]+=s[a[i][4]][a[i][5]][1];
        a[i][3]+=s[a[i][4]][a[i][5]][2];
      }
      for(int i=1;i<=n;i++)//4 h  5 f 
      {

        if(!a[i][12]||ch[i][k]=='N') continue;//如果已经坠毁或这次无操作就continue
        else if(ch[i][k]=='F'){//回血
        a[i][10]+=a[i][11];
        }
        else if(ch[i][k]=='L'){//若为上限则重载(循环  0,1,2,3,4,5,6,7,0,1  ……)
            if(a[i][5]==7) 
              a[i][5]=0;
            else
              a[i][5]++;
        }
        else if(ch[i][k]=='R'){//同上
            if(a[i][5]==0)
              a[i][5]=7;
            else
              a[i][5]--;
        }
        else if(ch[i][k]=='U'){//U/D 与L/R 不同 ,超过范围就为无效操作
            if(a[i][4]<4)
              a[i][4]++;
        }
        else if(ch[i][k]=='D'){//同上
            if(a[i][4]>0)
              a[i][4]--;
        }
        else if(ch[i][k]=='M'){
                int sum=0;//判断向前移动了几次。
                int xx=a[i][1],yy=a[i][2],zz=a[i][3];//记录当前飞机方位
                there2: xx+=s[a[i][4]][a[i][5]][0];//以下模拟移动
                yy+=s[a[i][4]][a[i][5]][1];
                zz+=s[a[i][4]][a[i][5]][2];
                sum++;//移动次数加1
                for(register int k=1;k<=n;++k){
                    if(!a[k][12]) continue;//如果飞机死亡
                    if(a[k][1]==xx&&a[k][2]==yy&&a[k][3]==zz){
                        int sh=a[i][8]-a[k][9];
                        if(sh>0){//如果差值为正数才有伤害
                            a[k][10]-=sh;
                            if(a[k][10]<=0){
                                a[k][12]=0;
                                a[k][11]=0;
                            }
                        }
                    }
                    if(sum>=100) break;//继续
                }
                if(sum<100) goto there2;//回到there2处(个人理解为变异的while循环)
            }
            else if(ch[i][k]=='A'){//子弹
                int sum=0;
                bool f=0;//判断有没有打到一架飞机
                int xx=a[i][1],yy=a[i][2],zz=a[i][3];
                there: xx+=s[a[i][4]][a[i][5]][0];//同上
                yy+=s[a[i][4]][a[i][5]][1];
                zz+=s[a[i][4]][a[i][5]][2];
                sum++;//移动次数加一
                for(int k=1;k<=n;++k){
                    if(!a[k][12]) continue;//如果当前这架飞机坠毁了,就continue
                    if(a[k][1]==xx&&a[k][2]==yy&&a[k][3]==zz){//如果当前到达了一架没有坠毁的飞机
                        f=1;//打到了,qwq;
                        int sh=a[i][6]-a[k][7];//计算伤害
                        if(sh>0){//扣除血量
                            a[k][10]-=sh;
                            if(a[k][10]<0){//因为坠毁的飞机最后输出时血量为0直接改成0
                                a[k][10]=0;
                                a[k][12]=0;//坠毁
                            }
                        }
                        break;//跳出循坏
                    }
                    if(sum>=100) f=1;//如果进行了100次以上的操作就直接跳出,卡数据
                }
                if(!f) goto there;//如果还没有打到就再移动
            }
       }

    }

    for(int i=1;i<=n;i++){
        cout<<a[i][1]<<" "<<a[i][2]<<" "<<a[i][3]<<" "<<a[i][10]<<endl; 
    }
    return 0;
}

码风粗陋,多多包涵