日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

信息学奥赛一本通 2006:【20CSPJ普及组】表达式 | 洛谷 P7073 [CSP-J2020] 表达式

發布時間:2025/3/17 编程问答 10 豆豆
生活随笔 收集整理的這篇文章主要介紹了 信息学奥赛一本通 2006:【20CSPJ普及组】表达式 | 洛谷 P7073 [CSP-J2020] 表达式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【題目鏈接】

ybt 2006:【20CSPJ普及組】表達式
洛谷 P7073 [CSP-J2020] 表達式

【題目考點】

  • 后綴表達式
  • 表達式樹
  • 通過后綴表達式建立表達式樹:

    • 遍歷后綴表達式字符串:
      • 若讀取到數字,生成結點,入棧
      • 若讀取到運算符,生成運算符結點,出棧兩個結點,分別作為運算符結點的左右孩子,將運算符結點入棧
    • 最后棧頂結點就是表達式樹的根結點

    【解題思路】

    • 題中求的是布爾表達式,問改變某個變量的值后,整個式子的值是否變化。
      由此可知,我們需要求出一個布爾型的數組isChange
      • isChange[i]為真,表示第i個變量變化后,表達式的值會變化。
      • isChange[i]為假時,表示第i個變量變化后,表達式的值不會變化。
    • 考察表達式a|b,當a為0,b為1時,0|1結果為0。此時如果a發生改變,式子變為1|1,結果為1。如果b發生改變,式子變為0|0結果為0。說明a的改變可以改變表達式的值,而b的改變不會改變表達式的值。
      由于運算數只有0、1,運算符只有&、|,可以枚舉不同的表達式中改變兩個變量后能否改變表達式的值,將這些情況保存起來,設為兩個數組isChAnd和isChOr。
      • isChAnd[a][b][c]: 在a&b這一表達式中,a(c為0)或b(c為1)的值變化能否影響運算的結果。
      • isChOr[a][b][c]: 在a|b這一表達式中,a(c為0)或b(c為1)的值變化能否影響運算的結果。
    • 通過后綴表達式建立表達式樹
      • 葉子結點記錄變量編號(x),變量值(val)
      • 每個子樹都是一個表達式。分支結點記錄以該結點為根的子樹所表示的表達式的值(val)、該結點的值如果變化對父結點的值是否有影響(inf)。
    • 判斷哪些變量變化會對整體表達式的值有影響,構造isChange數組
      • 如果一個結點的變化對其父結點沒有影響,那么該結點所有孩子結點的變化對父結點都沒有影響。即以該結點為根結點的子樹的葉子結點對應的變量的變化對整體表達式的值沒有影響。
      • 遍歷表達式樹,如果遇到自身值變化不會影響父結點的結點,那么,就不再向下遍歷。以此方法,遍歷到的所有葉子結點對應的變量,其變化都會影響整體表達式的值,對應地設置isChange數組。
    • 根據題目需要,查詢isChange數組,輸出結果。

    【題解代碼】

    解法1:

    #include <bits/stdc++.h> using namespace std; #define N 1000005 typedef struct Node//表達式樹結點 {int left, right;bool val;//值bool inf;//本節點值的改變是否能影響父結點int x;//該結點的變量編號 }Node; bool val[N];//val[i]:變量x[i]的初值 char s[N];//讀入的字符串 Node node[N];//結點池 int ni = 1;//結點池下標 bool isChange[N];//isChange[i] 第i個變量變化后,能否影響最終結果 //isChAnd[a][b][c]: 當第1個數的值是a,第2個數值是b時,第c+1個數的值變化能否影響運算的結果。 //例:0&0 = 0 第一個數0變為1,公式變為1&0 = 0,不能影響運算結果。那么有isChAnd[0][0][0] = false; bool isChAnd[2][2][2], isChOr[2][2][2]; //初始化isChAnd和isChOr void initIsCh() {isChAnd[0][0][0] = 0; isChAnd[0][0][1] = 0;isChAnd[0][1][0] = 1; isChAnd[0][1][1] = 0;isChAnd[1][0][0] = 0; isChAnd[1][0][1] = 1;isChAnd[1][1][0] = 1; isChAnd[1][1][1] = 1;isChOr[0][0][0] = 1; isChOr[0][0][1] = 1;isChOr[0][1][0] = 0; isChOr[0][1][1] = 1;isChOr[1][0][0] = 1; isChOr[1][0][1] = 0;isChOr[1][1][0] = 0; isChOr[1][1][1] = 0; } //生成表達式樹,返回根節點的地址 int initTree() {stack<int> stk;//存放結點地址int xNum = 0, np, lp, rp;//xNum:變量編號 np:新結點地址 lp,rp:左右孩子地址 char cal;//運算符int len = strlen(s);for(int i = 0; i <= len; ++i){if(s[i] >= '0' && s[i] <= '9')xNum = xNum * 10 + s[i] - '0';else if(s[i] == '&' || s[i] == '|' || s[i] == '!')cal = s[i];else if(s[i] == ' ' || s[i] == '\0'){if(xNum > 0)//提取出x{np = ni++; node[np].val = val[xNum];node[np].x = xNum;stk.push(np);xNum = 0;}else//提取出運算符{np = ni++;if(cal == '!'){lp = stk.top();stk.pop();node[lp].inf = true;//取非運算的運算數的改變會影響表達式的值node[np].val = !node[lp].val;node[np].left = lp;}else{rp = stk.top();stk.pop();lp = stk.top();stk.pop();node[np].left = lp;node[np].right = rp;if(cal == '&'){node[np].val = node[lp].val && node[rp].val;node[lp].inf = isChAnd[node[lp].val][node[rp].val][0];node[rp].inf = isChAnd[node[lp].val][node[rp].val][1];}else if(cal == '|'){node[np].val = node[lp].val || node[rp].val;node[lp].inf = isChOr[node[lp].val][node[rp].val][0];node[rp].inf = isChOr[node[lp].val][node[rp].val][1];}}stk.push(np);}}}return stk.top(); } //設置isChange數組 遍歷表達式樹 void initIsChange(int p) {if(node[p].inf)//如果該點值的變化不能影響父結點 ,就不遍歷了。{if(node[p].left == 0 && node[p].right == 0){isChange[node[p].x] = true;//如果遍歷到葉子結點,那么設置該變量的變化可以影響表達式的值}else{if(node[p].left != 0)initIsChange(node[p].left);if(node[p].right != 0)initIsChange(node[p].right);}} }int main() {initIsCh();int n, q, qi;bool res;//正常計算的結果cin.getline(s, N);scanf("%d", &n);for(int i = 1; i <= n; ++i)//輸入各個變量的值scanf("%d", &val[i]);int root = initTree();//生成表達式樹res = node[root].val;//通過已有變量值求出的表達式的原始結果node[root].inf = true;//為了配合下面的函數,必須設這一點initIsChange(root);//設置isChange數組scanf("%d", &q);//輸入查詢組數for(int i = 1; i <= q; ++i){scanf("%d", &qi);//改變第qi變量if(isChange[qi])//如果第qi變量的改變能引起表達式值的變化printf("%d\n", !res);//輸出變化后的結果elseprintf("%d\n", res);//輸出原結果}return 0; }

    總結

    以上是生活随笔為你收集整理的信息学奥赛一本通 2006:【20CSPJ普及组】表达式 | 洛谷 P7073 [CSP-J2020] 表达式的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。