题解:论如何利用 大 模 拟 吊打LGJ~

题目背景

出假题的lGJ又被机智的同学同学们打败了,
于是LGJ使用分神术复制了n个LGJ并且有的LGJ
有些LGJ带上了路障,也有带上了铁帽,还有的带上了撑杆。
你召唤了mi_ruo来保护自己的大本营。
数据较原先有加强(并不大,只是hack掉了跳两次可过的情况)

题目描述

mi_ruo可以分身成m个mi_ruo,LGJ距离你的大本营的距离为k
每个已经出现的LGJ向前走一次,如果LGJ走的格有mi_ruo,则mi_ruo会被带走(带走不耗时间)每回合每个mi_ruo发动一次可爱攻击。(LGJ先走,mi_ruo再发动可爱攻击,并且mi_ruo只能打最前方的LGJ,即本回合最前的LGJ gg了也不会对后面的LGJ造成伤害)
从第一格向后依次为一个mi_ruo(开局所有mi_ruo已准备好)。
如果LGJ没有出完每3回合出一次LGJ
以下为不同种类的LGJ的血量与速度

       血量    速度(次/格) 
普通    5       1   
路障    10      1
铁桶    20      1
撑杆    10      2      遇到第一个mi_ruo跳过速度变为1

以下为题意补充 :
About mi_ruo: 为”向LGJ“mi_ruo,即如果一只LGJ出现在她后面(并且此时她还没被LGJ带走),她会对LGJ造成伤害,所有mi_ruo都只会对第一个LGJ造成伤害
About LGJ:撑杆LGJ在出现时并不会出现在第K个格子里,它会直接出现在第K1个格子里,也就是从第K+1个格子里走了两格。
撑杆跳过mi_ruo的时候,如果前面两格(他在这一回合所能达到的地方)任意一格有mi_ruo,他会直接跳到第一个mi_ruo后边并把这个格子内的mi_ruo带走,被跳过的mi_ruo依旧存活
数据保证不会出现在同一个格子里出现两个LGJ的情况

输入格式

输入:n,m,k保证(m<k) 接下来n行输入LGJ的属性,1为普通,2为路障,3为铁桶,4为撑杆.

输出格式

输出:如果能击败所有LGJ第一行输出"water GJ you are so vegetable!"(引号不输出)第二行输出LGJ最多走到第几格。
(LGJ从第k格向第一格走,可以理解为从第k+1格开始走)
如果LGJ可以进入大本营第一行输出"cimao GJ wins...!what fuck"
第二行输出第几个LGJ首先进入大本营。

输入输出样例

输入 #1
2  2  10 
1
1
输出 #1
water GJ you are so vegetable!
8

说明/提示

全部输入数据均小于50
实际最大点才30

关于问题:

在原Oj里面并没有注明同一格中不会同时出现两个LGJ,所以本篇代码是按会出现去写的。

首先是变量的定义:

struct zombie{
    int hp,sp;//hp为当前僵尸的血量,sp为当前僵尸能移动的格数
    bool jp;//jp为当前僵尸能否跳跃
} zb[50];//zb[i]结构体存储第i只僵尸的数据
int m,n,k,type,tt=1,mi=999;//m为草坪长度,n为僵尸数量,k为豌豆数量,type在输入时获取僵尸的类型,tt存储当前出到第几只僵尸了,mi记录僵尸走得最远的格子
int typehp[5]={0,5,10,20,10},typesp[5]={0,1,1,1,2};
//这两个数组用以获取该类型僵尸的数据

之后输入各种数据:

cin>>n>>k>>m;
    for(int i=1;i<=n;i++)
    {
        cin>>type;
        zb[i].hp=typehp[type];
        zb[i].sp=typesp[type];
        if(type==4) zb[i].jp=1;
    }//输入僵尸属性

我们可以建一个数组,去模拟草坪上的状况。

1 int lawn[3][150],k;//k为豌豆数量
2         lawn[0][0]=-2;
3     for(int i=1;i<=k;i++) lawn[0][i]=-1;
4     //建立草坪,-2为家,-1为豌豆 ,lawn[0]存家,豌豆和这一格上的僵尸数
5     //lawn[1]存这一格上的第一只僵尸的编号,lawn[2]存这一格上的第二只僵尸的编号  

如果表示出来的话,在实际运行中是这种感觉:

-2 -1 1 -1 0 2 0 0 0 1
0 0 1 0 0 2 0 0 0 4
0 0 0 0 0 3 0 0 0 0

其中,第一行就是lawn[0],-2表示这一格是家,-1表示这一格上是豌豆,0表示这一格为空,正整数表示这一格上僵尸的数量。

第二,三行存储该格子上僵尸的编号,就是zb[i]中的i。

所以我们可以通过这个获取该僵尸的所有数据。

撒,开始我们的模拟吧~~~

关于模拟的过程,都打在代码的注释里了。

关于僵尸的移动:

for(int round=3;round<=3*n+m+2;round++)//进行模拟 ,3*n+m+2保证所有僵尸都有走到家里的机会 
    {
        if(round%3==0&&round<=3*n) lawn[0][m+1]=1,lawn[1][m+1]=tt++;
        //每三回合出一只僵尸
        for(int i=1;i<=m+1;i++)//僵尸先走 
        {
            if(lawn[0][i]>0)//若此格上僵尸数大于0 
            for(int r=1;r<=2;r++)//遍历这一格上所有僵尸
            {
                int p=lawn[r][i];//p为当前僵尸标号
                if(p!=0)
                for(int t=1;t<=zb[p].sp;t++)//僵尸进行移动 
                {
                    if(i-t<mi)mi=i-t;
                    int nxt=lawn[0][i-t];//nxt为僵尸要移动到的格子
                    if(nxt==-2) {cout<<"cimao GJ wins...!what fuck"<<endl<<p;return 0;} 
                    //若下一格是家,则僵尸胜,终止程序
                    else if(nxt==-1)//若下一格为豌豆 
                    {
                        if(zb[p].jp==1)//若僵尸能跳
                        {
                            if(i-t-1<mi)mi=i-t-1;
                            if(lawn[0][i-t-1]==-2) {cout<<"cimao GJ wins...!what fuck"<<endl<<p;return 0;} 
                            else 
                            {
                                lawn[0][i-t-1]=1;lawn[1][i-t-1]=p;
                                lawn[0][i-t+1]--;lawn[r][i-t+1]=0;
                                zb[p].jp=0;zb[p].sp=1;
                            }//跳过面前的植物 ,改变跳跃状态和速度 
                        }
                        else//若僵尸不能跳 
                        {
                            lawn[0][i-t]=1;lawn[1][i-t]=p;
                            lawn[0][i-t+1]--;lawn[r][i-t+1]=0;
                        }//把豌豆吃了 
                    }
                    else if(nxt==1)//若下一格有僵尸
                    {
                        lawn[0][i-t]=2;lawn[2][i-t]=p;
                        lawn[0][i-t+1]--;lawn[r][i-t+1]=0;
                    }//存在lawn[2]里 
                    else//若下一格为空 
                    {
                        lawn[0][i-t]=1;lawn[1][i-t]=p;
                        lawn[0][i-t+1]--;lawn[r][i-t+1]=0;
                    }
                } 
            }
        }

然后关于豌豆的攻击:

int dmg=0;//初始化伤害 
        for(int i=1;i<=m;i++)//植物再打
        {
            if(lawn[0][i]==-1) dmg++;//若这格上是豌豆,则累积伤害 
        }
        for(int i=1;i<=m;i++)//再从头寻找第一只僵尸 
        {
            if(lawn[0][i]>0)//这一格上僵尸数大于0
            {
                int p=lawn[1][i];
                zb[p].hp-=dmg;
                dmg=0;
                if(zb[p].hp<=0)
                {
                    lawn[0][i]--;
                    lawn[1][i]=0;
                }
                break; 
            }//对其造成伤害,伤害值归零,若僵尸死亡,将其从草坪中清除 
        }
    }//如过前面没有一只僵尸到达家里,就输出下面这个~ 
    cout<<"water GJ you are so vegetable!"<<endl<<mi;

 

很多地方其实都能优化,但这题数据范围实在太水了,没有必要,所以我就懒得改辣~

最后是高清完整版代码:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 struct zombie{
  4     int hp,sp;
  5     bool jp;
  6 } zb[50];
  7 int m,n,k,lawn[3][150],type,tt=1,mi=999;
  8 int typehp[5]={0,5,10,20,10},typesp[5]={0,1,1,1,2};
  9 int main()
 10 {
 11     cin>>n>>k>>m;
 12     for(int i=1;i<=n;i++)
 13     {
 14         cin>>type;
 15         zb[i].hp=typehp[type];
 16         zb[i].sp=typesp[type];
 17         if(type==4) zb[i].jp=1;
 18     }//输入僵尸属性
 19     lawn[0][0]=-2;
 20     for(int i=1;i<=k;i++) lawn[0][i]=-1;
 21     //建立草坪,-2为家,-1为豌豆 ,lawn[0]存家,豌豆和这一格上的僵尸数
 22     //lawn[1]存这一格上的第一只僵尸,lawn[2]存这一格上的第二只僵尸
 23     for(int round=3;round<=3*n+m+2;round++)//进行模拟 ,3*n+m+2保证所有僵尸都有走到家里的机会 
 24     {
 25         if(round%3==0&&round<=3*n) lawn[0][m+1]=1,lawn[1][m+1]=tt++;
 26         //每三回合出一只僵尸
 27         for(int i=1;i<=m+1;i++)//僵尸先走 
 28         {
 29             if(lawn[0][i]>0)//若此格上僵尸数大于0 
 30             for(int r=1;r<=2;r++)//遍历这一格上所有僵尸
 31             {
 32                 int p=lawn[r][i];//p为当前僵尸标号
 33                 if(p!=0)
 34                 for(int t=1;t<=zb[p].sp;t++)//僵尸进行移动 
 35                 {
 36                     if(i-t<mi)mi=i-t;
 37                     int nxt=lawn[0][i-t];//nxt为僵尸要移动到的格子
 38                     if(nxt==-2) {cout<<"cimao GJ wins...!what fuck"<<endl<<p;return 0;} 
 39                     //若下一格是家,则僵尸胜,终止程序
 40                     else if(nxt==-1)//若下一格为豌豆 
 41                     {
 42                         if(zb[p].jp==1)//若僵尸能跳
 43                         {
 44                             if(i-t-1<mi)mi=i-t-1;
 45                             if(lawn[0][i-t-1]==-2) {cout<<"cimao GJ wins...!what fuck"<<endl<<p;return 0;} 
 46                             else 
 47                             {
 48                                 lawn[0][i-t-1]=1;lawn[1][i-t-1]=p;
 49                                 lawn[0][i-t+1]--;lawn[r][i-t+1]=0;
 50                                 zb[p].jp=0;zb[p].sp=1;
 51                             }//跳过面前的植物 ,改变跳跃状态和速度 
 52                         }
 53                         else//若僵尸不能跳 
 54                         {
 55                             lawn[0][i-t]=1;lawn[1][i-t]=p;
 56                             lawn[0][i-t+1]--;lawn[r][i-t+1]=0;
 57                         }//把豌豆吃了 
 58                     }
 59                     else if(nxt==1)//若下一格有僵尸
 60                     {
 61                         lawn[0][i-t]=2;lawn[2][i-t]=p;
 62                         lawn[0][i-t+1]--;lawn[r][i-t+1]=0;
 63                     }//存在lawn[2]里 
 64                     else//若下一格为空 
 65                     {
 66                         lawn[0][i-t]=1;lawn[1][i-t]=p;
 67                         lawn[0][i-t+1]--;lawn[r][i-t+1]=0;
 68                     }
 69                 } 
 70             }
 71         }
 72         //----------------------------------调试用,输出草坪状况------------------------------------- 
 73         /*cout<<"round:"<<round<<endl;
 74         for(int i=0;i<=2;i++)
 75         {
 76             for(int r=0;r<=m+1;r++)
 77             {
 78                 printf("%3d ",lawn[i][r]);
 79             }
 80             cout<<endl;
 81          } 
 82          cout<<"--------------------------------------------------"<<endl;*/
 83         //----------------------------------调试用,输出草坪状况------------------------------------
 84         int dmg=0;//初始化伤害 
 85         for(int i=1;i<=m;i++)//植物再打
 86         {
 87             if(lawn[0][i]==-1) dmg++;//若这格上是豌豆,则累积伤害 
 88         }
 89         for(int i=1;i<=m;i++)//再从头寻找第一只僵尸 
 90         {
 91             if(lawn[0][i]>0)//这一格上僵尸数大于0
 92             {
 93                 int p=lawn[1][i];
 94                 zb[p].hp-=dmg;
 95                 dmg=0;
 96                 if(zb[p].hp<=0)
 97                 {
 98                     lawn[0][i]--;
 99                     lawn[1][i]=0;
100                 }
101                 break; 
102             }//对其造成伤害,伤害值归零,若僵尸死亡,将其从草坪中清除 
103         }
104     }//如过前面没有一只僵尸到达家里,就输出下面这个~ 
105     cout<<"water GJ you are so vegetable!"<<endl<<mi; 
106 } 

完结撒花~

(然而洛谷上莫名其妙会RE不要在意那么多细节

原文地址:https://www.cnblogs.com/MagicConchh/p/13447973.html