1. 程式人生 > >NOIP-模擬試題之--時間複雜度題解

NOIP-模擬試題之--時間複雜度題解

2018 NOIP 全套資料下載
描述
小明正在學習一種新的程式語言 A++,剛學會迴圈語句的他激動地寫了好多程式並 給出了他自己算出的時間複雜度,可他的程式設計老師實在不想一個一個檢查小明的程式, 於是你的機會來啦!下面請你編寫程式來判斷小明對他的每個程式給出的時間複雜度是否正確。

A++語言的迴圈結構如下:

F i x y
迴圈體
E
其中F i x y表示新建變數 ii(變數 ii 不可與未被銷燬的變數重名)並初始化為 xx, 然後判斷 ii 和 yy 的大小關係,若 ii 小於等於 yy 則進入迴圈,否則不進入。每次迴圈結束後 ii 都會被修改成 i+1i+1,一旦 ii 大於 yy 終止迴圈。

xx 和 yy 可以是正整數(xx 和 yy 的大小關係不定)或變數 nn。nn 是一個表示資料規模的變數,在時間複雜度計算中需保留該變數而不能將其視為常數,該數遠大於 100。

“E”表示迴圈體結束。迴圈體結束時,這個迴圈體新建的變數也被銷燬。

注:本題中為了書寫方便,在描述複雜度時,使用大寫英文字母“O”表示通常意義下“Θ”的概念。

輸入

輸入檔案第一行一個正整數 tt,表示有 tt(t≤10t≤10)個程式需要計算時間複雜度。 每個程式我們只需抽取其中 F i x y和E即可計算時間複雜度。注意:迴圈結構允許巢狀。

接下來每個程式的第一行包含一個正整數 LL 和一個字串,LL 代表程式行數,字串表示這個程式的複雜度,O(1)表示常數複雜度,O(nw)表示複雜度為nwnw,其中w是一個小於100的正整數(輸入中不包含引號),輸入保證複雜度只有O(1)和O(n

w) 兩種型別。

接下來 LL 行代表程式中迴圈結構中的F i x y或者 E。 程式行若以F開頭,表示進入一個迴圈,之後有空格分離的三個字元(串)i x y, 其中 ii 是一個小寫字母(保證不為nn),表示新建的變數名,xx 和 yy 可能是正整數或 nn ,已知若為正整數則一定小於 100。

程式行若以E開頭,則表示迴圈體結束。

輸出

輸出檔案共 tt 行,對應輸入的 tt 個程式,每行輸出”Yes”或”No”或者”ERR”(輸出中不包含引號),若程式實際複雜度與輸入給出的複雜度一致則輸出”Yes”,不一致則輸出”No”,若程式有語法錯誤(其中語法錯誤只有: ① F 和 E 不匹配 ②新建的變數與已經存在但未被銷燬的變數重複兩種情況),則輸出”ERR” 。

注意:即使在程式不會執行的迴圈體中出現了語法錯誤也會編譯錯誤,要輸出 ERR。

樣例輸入
8
2 O(1)
F i 1 1
E
2 O(n^1)
F x 1 n
E
1 O(1)
F x 1 n
4 O(n^2)
F x 5 n
F y 10 n
E
E
4 O(n^2)
F x 9 n
E
F y 2 n
E
4 O(n^1)
F x 9 n
F y n 4
E
E
4 O(1)
F y n 4
F x 9 n
E
E
4 O(n^2)
F x 1 n
F x 1 10
E
E
樣例輸出

Yes
Yes
ERR
Yes
No
Yes
Yes
ERR
輸入輸出樣例解釋

第一個程式 ii 從 1 到 1 是常數複雜度。
第二個程式 xx 從 1 到 nn 是 nn 的一次方的複雜度。
第三個程式有一個 F 開啟迴圈卻沒有 E 結束,語法錯誤。
第四個程式二重迴圈,nn 的平方的複雜度。
第五個程式兩個一重迴圈,nn 的一次方的複雜度。
第六個程式第一重迴圈正常,但第二重迴圈開始即終止(因為nn遠大於100,100大於4)。
第七個程式第一重迴圈無法進入,故為常數複雜度。
第八個程式第二重迴圈中的變數 xx 與第一重迴圈中的變數重複,出現語法錯誤②,輸出 ERR。

資料規模與約定

對於 30%的資料:不存在語法錯誤,資料保證小明給出的每個程式的前 L/2L/2 行一定為以 F 開頭的語句,第 L/2+1L/2+1 行至第 LL 行一定為以 EE 開頭的語句,L≤10L≤10,若 xx、yy 均 為整數,xx 一定小於 yy,且只有 yy 有可能為 nn。

對於 50%的資料:不存在語法錯誤,L≤100L≤100,且若 xx、yy 均為整數,xx 一定小於 yy, 且只有 yy 有可能為 nn。

對於 70%的資料:不存在語法錯誤,L≤100L≤100。

對於 100%的資料:L≤100L≤100。

解題思路

由於迴圈必須要讓F與E配對,聯想到括號匹配問題,所以用棧來模擬。
為了方便計算,我在棧裡維護了三個值,分別表示當前迴圈所用變數名、程式執行到當前迴圈時的複雜度、當前迴圈是否處於被跳過的迴圈之中(即程式不會執行到)。在壓棧時維護一下這三個值就好了,最後的複雜度即為最大的可被執行到的複雜度。
最後,注意一下關於字串的讀入處理就好了。
Code

#include
#include
#include
#include

using namespace std;

int T, L, kind, w;//kind == 1:O(1); kind == 2: O(n^w)
int top, ans;
char com[100], opt[100];
bool used[1000], err;
struct Node{
char ch;
int c;//執行至此的時間複雜度
bool dir;//是否處於直接跳過的迴圈中
}sta[1000];

void solve(){
scanf("%d ", &L);
cin.getline(com, 99);
if(com[2] == ‘1’) kind = 1;
else{
int now = 4;
while(com[now] >= ‘0’ && com[now] <= ‘9’){
w = w * 10 + com[now] - ‘0’;
now++;
}
kind = 2;
}
for(int i = 1; i <= L; i++){
cin.getline(opt, 99);
if(err) continue;
if(opt[0] == ‘F’){
if(used[opt[2]]){ err = 1; continue; }
used[opt[2]] = 1;
int now = 4, l = 0, r = 0, pre = 0, nxt = 0;
while((opt[now] >= ‘0’ && opt[now] <= ‘9’) || opt[now] == ‘n’){
if(opt[now] == ‘n’) pre = 1;
else l = l * 10 + opt[now] - ‘0’;
now++;
}
now++;
while((opt[now] >= ‘0’ && opt[now] <= ‘9’) || (opt[now] == ‘n’)){
if(opt[now] == ‘n’) nxt = 1;
else r = r * 10 + opt[now] - ‘0’;
now++;
}
if(pre == 1 && nxt == 1){
sta[top+1] = (Node){opt[2], sta[top].c, sta[top].dir};
top++;
if(sta[top].dir == 0) ans = max(ans, sta[top].c);
}
else if(pre == 1 && nxt == 0){
sta[top+1] = (Node){opt[2], sta[top].c, 1};
top++;
}
else if(pre == 0 && nxt == 1){
sta[top+1] = (Node){opt[2], sta[top].c + 1, sta[top].dir};
top++;
if(sta[top].dir == 0) ans = max(ans, sta[top].c);
}
else if(pre == 0 && nxt == 0){
if(l <= r){
sta[top+1] = (Node){opt[2], sta[top].c, sta[top].dir};
top++;
if(sta[top].dir == 0) ans = max(ans, sta[top].c);
}
else{
sta[top+1] = (Node){opt[2], sta[top].c, 1};
top++;
}
}
}
else if(opt[0] == ‘E’){
if(top == 0) err = 1;
else{
used[sta[top].ch] = 0;
top–;
}
}
}
if(top) err = 1;
if(err){ puts(“ERR”); return; }
if(kind == 1 && ans == 0){ puts(“Yes”); return; }
if(kind == 2 && w == ans){ puts(“Yes”); return; }
puts(“No”); return;
}

void init(){
memset(sta, 0, sizeof sta); top = 0;
memset(com, 0, sizeof com);
memset(opt, 0, sizeof opt);
memset(used, 0, sizeof used);
err = 0;
ans = 0;
kind = w = 0;
}

int main(){
scanf("%d", &T);
while(T–){
init();
solve();
}
return 0;
}


原文:https://blog.csdn.net/PhantomAgony/article/details/78703721