洛谷 P3952 時間復雜度
阿新 • • 發佈:2018-03-02
不能 時間復雜度 收獲 進行 return pos 是否 這就是 esp
做這道題的最大收獲就是堅持不懈,勇往直前,這道題是一個“碼力題”,不能說無腦,但絕對惡心。總共花了3h+才調出來。果然當時NOIp放棄這道題是明智的
好了,閑話放一邊,我們來搞一搞這道題。
這道題思路很簡單,就是模擬。t<=10和L<=100也提示了我們時間不是問題,要大膽的去模擬。我是在線判斷程序是否ERR,離線判斷時間復雜度計算是否正確。如果程序ERR,就標記一下,輸入完之後直接結束這次循環(continue),不再進行接下來的計算。至於判斷Yes和No,我先將輸入的時間復雜度記錄下來,自己再算一遍時間復雜度,和所給的比對,來判斷Yes和No(做法很亂,請讀者老爺們包容)。
這是一個基本思路,中間還有許多特判,包括:
兩個ERR的判斷:第一個用的棧的思想,第二個用的桶的思想
因為我是輸入的字符串,所以還要將字符串中的數字扣下來,便於使用和比對
判斷該層循環能否進去
有可能出現幾個循環並列在同一層的情況
尋找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 時間復雜度