題目描述
小L熱衷於undercards. 在undercards中,有四個格子。每個格子要么是空的,要么住着一只BigBob。 每個BigBob有一個不超過k的血量;血量減到0視為死亡。那個格子隨即空
出。
當一只BigBob受到傷害后,假如它沒有死亡且剩余血量為t,它會從左數第 一個空格處召喚一只血量為a[t]的BigBob;若沒有空格,則不會召喚。
法術R定義為:從左往右,對每個BigBob造成一點傷害;假如有BigBob死 亡,重復上述效果。
聰明的小L發現,在某些情況下,當他發動法術R時,游戲會陷入循環。 他想求出這樣的初始情形有多少種。
出。
當一只BigBob受到傷害后,假如它沒有死亡且剩余血量為t,它會從左數第 一個空格處召喚一只血量為a[t]的BigBob;若沒有空格,則不會召喚。
法術R定義為:從左往右,對每個BigBob造成一點傷害;假如有BigBob死 亡,重復上述效果。
聰明的小L發現,在某些情況下,當他發動法術R時,游戲會陷入循環。 他想求出這樣的初始情形有多少種。
輸入
輸入一個正整數k;
隨后一行k-1個正整數,表示a[1]~a[k-1];
隨后一行k-1個正整數,表示a[1]~a[k-1];
輸出
輸出一個整數,表示答案。
樣例輸入
2
2
樣例輸出
31
提示
【樣例解釋】
Bigbob最多有2血,滿血bigbob受傷會召出新的。 循環的初始狀態有:
(2,1,0,0),(1,2,0,0),(2,0,1,0),(2,1,1,0),(0,2,1,0),(1,2,1,0),(2,2,1,0),(1,0,2,0),(0,1,2,0),(1,1,2,0),(2,1,2,0),(2,1,0,1),(0,2,0,1),(1,2,0,1),(0,2,1,1),(1,2,1,1),(0,0,2,1),(1,0,2,1),0,1,2,1),(1,1,2,1),(2,1,2,1),(0,2,2,1),(1,2,2,1),(2,1,0,2),(1,2,0,2),(2,0,1,2),(2,1,1,2),(0,2,1,2),(1,2,1,2),(2,2,1,2),(2,1,2,2)
共31種。
【數據范圍】
對於30%的數據,k≤5; 對於70%的數據,k≤10, a[i]=k; 對於100%的數據,k≤15, 1≤a[i]≤k。
Bigbob最多有2血,滿血bigbob受傷會召出新的。 循環的初始狀態有:
(2,1,0,0),(1,2,0,0),(2,0,1,0),(2,1,1,0),(0,2,1,0),(1,2,1,0),(2,2,1,0),(1,0,2,0),(0,1,2,0),(1,1,2,0),(2,1,2,0),(2,1,0,1),(0,2,0,1),(1,2,0,1),(0,2,1,1),(1,2,1,1),(0,0,2,1),(1,0,2,1),0,1,2,1),(1,1,2,1),(2,1,2,1),(0,2,2,1),(1,2,2,1),(2,1,0,2),(1,2,0,2),(2,0,1,2),(2,1,1,2),(0,2,1,2),(1,2,1,2),(2,2,1,2),(2,1,2,2)
共31種。
【數據范圍】
對於30%的數據,k≤5; 對於70%的數據,k≤10, a[i]=k; 對於100%的數據,k≤15, 1≤a[i]≤k。
解析:
在orz了石神和陳神后(如果你是SRY同學那么可以默默地離開了),蒟蒻終於非獨立自主地做出了這道題。。。
首先我們摟一眼這玩意,一看就是個深搜嗎。。。k<=15啊~,此時不搜更待何時呢。。。
四個空格,首先根據題意,我們要先去枚舉四個格子里的數字,直接dfs即可,接下來我們去考慮一下
如何判定,由於只有四個空格,我們完全可以開一個pd數組,而pd[a][b][c][d]==1就代表出現過第一個格子為a......第四個格子為d的這種情況(蒟蒻太懶,dalao請自行腦補);
由於每次都得重新來,所以每次都要清空。。(我最開始怕RE,開了個50*50*50*50的數組,每次清空費了大量時間。。。【感謝偉大的石神幫我調了出來。。。】)
然后只要按照規則來就好嘞~~~,如果有被殺死的,那就接着來,如果四個都被殺死了,就返回,還有一點要注意的是,這個pd()函數里的數組不能和dfs排列的數組混了,因為
是按序枚舉,你把它改了,但是dfs函數不知道呀,,,還是接着枚舉,下面給大家看看標准的錯誤代碼:

1 bool pd1[50][50][50][50],f; 2 void pd() 3 { 4 memset(pd1,0,sizeof(pd1)); 5 while(1) 6 { 7 f=0; 8 pd1[gz[1]][gz[2]][gz[3]][gz[4]]=1; 9 for(int i=1;i<=4;i++) 10 { 11 if(gz[i]==1)f=1; 12 if(gz[i]>=1)gz[i]--; 13 for(int j=1;j<=4;j++) 14 { 15 if(i==j)continue; 16 if(gz[j]==0) 17 { 18 gz[j]=a[gz[i]]; 19 break; 20 } 21 } 22 } 23 if(gz[1]+gz[2]+gz[3]+gz[4]==0||f==0) 24 { 25 return; 26 } 27 if(pd1[gz[1]][gz[2]][gz[3]][gz[4]]) 28 { 29 total++; 30 return; 31 } 32 } 33 } 34 void dfs(int t) 35 { 36 for(int i=0;i<=k;i++) 37 { 38 gz[t]=i; 39 if(t==4)pd(); 40 else dfs(t+1); 41 } 42 }
這個程序,又T又WA,可謂是WA,T兩開花~,今年下半年中美合拍的西游記即將正式開機。。。
最后上AC代碼:

1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 int k,a[20],gz[5],total,s,now[5]; 6 bool pd1[16][16][16][16],f;//pd不能開太大,否則會T 7 inline void pd() 8 { 9 memset(pd1,0,sizeof(pd1)); 10 /*cout<<gz[1]<<" "<<gz[2]<<" "<<gz[3]<<" "<<gz[4]<<endl;*/ 11 for(int i=1;i<=4;i++)gz[i]=now[i];//不能用排列的數組,否則會WA 12 while(1) 13 { 14 f=0; 15 pd1[gz[1]][gz[2]][gz[3]][gz[4]]=1; 16 for(int i=1;i<=4;i++) 17 { 18 if(gz[i]<1) continue; 19 gz[i]--; 20 if(gz[i]==0) 21 { 22 f=1; 23 continue; 24 } 25 for(int j=1;j<=4;j++) 26 { 27 if(i==j)continue; 28 if(gz[j]==0) 29 { 30 gz[j]=a[gz[i]]; 31 break; 32 } 33 } 34 } 35 if(gz[1]+gz[2]+gz[3]+gz[4]==0||!f)return; 36 if(pd1[gz[1]][gz[2]][gz[3]][gz[4]]) 37 { 38 total++; 39 return; 40 } 41 } 42 } 43 inline void dfs(int t)//生成四個格子的排列 44 { 45 if(t==5) 46 { 47 pd(); 48 return; 49 } 50 for(int i=0;i<=k;i++) 51 { 52 now[t]=i; 53 dfs(t+1); 54 } 55 } 56 int main() 57 { 58 cin>>k; 59 for(int i=1;i<=k-1;i++)cin>>a[i]; 60 dfs(1); 61 cout<<total; 62 return 0; 63 }
時間復雜度最大為O(15*15*15*15*(memset函數速度蒟蒻不會算+10(pd函數while(1)運行的平均次數))≈ O(8100000);穩~
這篇題解這么好,不關注+素質三連嗎???