恐怖的奴隸主(bob)


 

題目描述

小L熱衷於undercards. 在undercards中,有四個格子。每個格子要么是空的,要么住着一只BigBob。 每個BigBob有一個不超過k的血量;血量減到0視為死亡。那個格子隨即空
出。
當一只BigBob受到傷害后,假如它沒有死亡且剩余血量為t,它會從左數第 一個空格處召喚一只血量為a[t]的BigBob;若沒有空格,則不會召喚。
法術R定義為:從左往右,對每個BigBob造成一點傷害;假如有BigBob死 亡,重復上述效果。
聰明的小L發現,在某些情況下,當他發動法術R時,游戲會陷入循環。 他想求出這樣的初始情形有多少種。

輸入

輸入一個正整數k;
隨后一行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。
 
 

解析:

在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 }
View Code

 

  這個程序,又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 }
View Code

 

 

 

  時間復雜度最大為O(15*15*15*15*(memset函數速度蒟蒻不會算+10(pd函數while(1)運行的平均次數))≈ O(8100000);穩~

這篇題解這么好,不關注+素質三連嗎???

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM