題解:論如何利用 大 模 擬 吊打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造成傷害)
如果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個格子裡,它會直接出現在第K−1個格子裡,也就是從第K+1個格子裡走了兩格。
資料保證不會出現在同一個格子裡出現兩個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首先進入大本營。
輸入輸出樣例
輸入 #12 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 }