1. 程式人生 > 實用技巧 >題解:論如何利用 大 模 擬 吊打LGJ~

題解:論如何利用 大 模 擬 吊打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不要在意那麼多細節