1. 程式人生 > >洛谷 P3952 時間復雜度

洛谷 P3952 時間復雜度

不能 時間復雜度 收獲 進行 return pos 是否 這就是 esp

做這道題的最大收獲就是堅持不懈,勇往直前,這道題是一個“碼力題”,不能說無腦,但絕對惡心。總共花了3h+才調出來。果然當時NOIp放棄這道題是明智的

好了,閑話放一邊,我們來搞一搞這道題。

這道題思路很簡單,就是模擬。t<=10和L<=100也提示了我們時間不是問題,要大膽的去模擬。我是在線判斷程序是否ERR,離線判斷時間復雜度計算是否正確。如果程序ERR,就標記一下,輸入完之後直接結束這次循環(continue),不再進行接下來的計算。至於判斷Yes和No,我先將輸入的時間復雜度記錄下來,自己再算一遍時間復雜度,和所給的比對,來判斷Yes和No(做法很亂,請讀者老爺們包容)。

這是一個基本思路,中間還有許多特判,包括:

  1. 兩個ERR的判斷:第一個用的棧的思想,第二個用的桶的思想

  2. 因為我是輸入的字符串,所以還要將字符串中的數字扣下來,便於使用和比對

  3. 判斷該層循環能否進去

  4. 有可能出現幾個循環並列在同一層的情況

  5. 尋找O(n)最大循環層數,就是時間復雜度,O(1)的情況直接不考慮

這就是我的一個大致思路,具體實現可以看我的代碼

#include<bits/stdc++.h>
using namespace std;
int t;
string ans[101];
bool flag[127];//雖然這是一個數組,但卻只用到了flag[22]
               //flag[22]:判斷該層循環能否進入。 
int flag2,tong[27];//flag2用來判斷ERR 1;tong用來判斷ERR 2 int yyy,tot,a,maxx;//yyy記錄當前所在循環的時間復雜度 //tot記錄當前所在的循環 //a記錄輸入的時間復雜度 n^w中的w //maxx記錄正確的w bool boom[100]; //boom[i]記錄第i層循環是否到過 int main() { cin>>t; //======輸入,同時判斷是否ERR for(int i=1;i<=t;i++) { tot=0
,flag2=0,memset(tong,0,sizeof(tong)),a=0; int l; cin>>l; string o; cin>>o; if(o[2]==‘n‘) //因為n的位置固定,所以直接判斷該位置是否為n //下面的求a和摳數也是同理 { a=o[4]-‘0‘; if(o[5]>=‘0‘&&o[5]<=‘9‘) a=a*10+o[5]-‘0‘; } char codes[101][101]; getchar(); for(int j=1;j<=l;j++) for(int k=0;k<=10;k++) { codes[j][k]=‘ ‘; } for(int j=1;j<=l;j++) { gets(codes[j]); //=====ERR 1 if(codes[j][0]==‘F‘) flag2++; //棧的思想,類似於括號匹配 if(codes[j][0]==‘E‘) flag2--; if(flag2<0) ans[i]="ERR"; //=====ERR 2 if(codes[j][0]==‘F‘) { if(tong[codes[j][2]-‘a‘+1]==0) //桶的思想 tong[codes[j][2]-‘a‘+1]=++tot; //因為循環結束後變量銷毀,所以要記錄循環層數 else ans[i]="ERR"; } if(codes[j][0]==‘E‘) { for(int i=1;i<=26;i++) { if(tong[i]==tot) // 銷毀變量 tong[i]=0; } tot--; } } if(flag2>0) ans[i]="ERR"; if(ans[i]=="ERR") continue; //如果ERR,不執行下面的操作 //================ERR finish tot=0;int zzz=0;flag[22]=0;yyy=0;memset(boom,0,sizeof(boom));maxx=0; //一定要初始化 for(int j=1;j<=l;j++) { if(codes[j][0]==‘F‘) { tot++; if(codes[j][4]==‘n‘&&((codes[j][6]>‘0‘&&codes[j][6]<=‘9‘)||(codes[j][7]>‘0‘&&codes[j][7]<=‘9‘))&&!flag[22]) { flag[22]=1; //因為n>任何一個整數,所以該層循環無法進入 zzz=tot; //zzz記錄無法進入的循環層數 } if(codes[j][4]>=‘0‘&&codes[j][4]<=‘9‘&&!flag[22]&&(codes[j][6]!=‘n‘&&codes[j][7]!=‘n‘)) { // 如果兩個都是常數,那麽暴力摳數,比較兩個數的大小 int c1=codes[j][4]-‘0‘; int c2; if(codes[j][5]>=‘0‘&&codes[j][5]<=‘9‘) c1=c1*10+codes[j][5]-‘0‘; if(c1<10) if(codes[j][6]>=‘0‘&&codes[j][6]<=‘9‘) { c2=codes[j][6]-‘0‘; if(codes[j][7]>=‘0‘&&codes[j][7]<=‘9‘) c2=c2*10+codes[j][7]-‘0‘; } if(c1>10) if(codes[j][7]>=‘0‘&&codes[j][7]<=‘9‘) { c2=codes[j][7]-‘0‘; if(codes[j][8]>=‘0‘&&codes[j][8]<=‘9‘) c2=c2*10+codes[j][8]-‘0‘; } if(c1>c2) //前面的數大於後面的數 { flag[22]=1; zzz=tot; } } if((codes[j][6]==‘n‘||codes[j][7]==‘n‘)&&codes[j][4]!=‘n‘&&!flag[22]) //該層循環可以進去 { if(!boom[tot]) //且沒有進去過同層的循環,因為如果進去過同層的循環,那麽這次循環不會影響時間復雜度 { boom[tot]=1; //標記 yyy++; //記錄當前的時間復雜度 if(yyy>maxx) //如果yyy此時大於maxx,更新maxx maxx=yyy; } } } if(codes[j][0]==‘E‘) { if(tot==zzz) flag[22]=0; //如果之前該層循環無法進入,那麽到同層的E,該層循環結束,以後的循環就可以進去了 if(boom[tot]) { yyy--; //如果到過這層循環,退出這層循環 boom[tot]=0; //再次標記該層循環未到過,防止特判4出現 } tot--; //層數減一 } } if(maxx==a) //比較輸入的時間復雜度和我們算出的正解 ans[i]="Yes"; else ans[i]="No"; } for(int i=1;i<=t;i++) cout<<ans[i]<<endl; return 0; } // 140行,完結撒花

洛谷 P3952 時間復雜度