1. 程式人生 > >【Codeforces 115D】Unambiguous Arithmetic Expression

【Codeforces 115D】Unambiguous Arithmetic Expression

連續 分段 思路 每一個 多少 人的 這一 force 答案

Codeforces 115 D

題意:給一個沒有括號的表達式,問有多少種添加括號的方法使得這是一個合法的表達式?輸入可能有正負號、加減乘除、數字。

思路1:

這是不能過的\(naive\)\(dp\)

考慮\(dp(l,r)\)表示從第\(l\)個字符到第\(r\)個字符有多少種添加括號的方法。

轉移的時候就枚舉當前最後一次運算。

思路2:

這是\(tourist\)的神奇\(dp\)

考慮\(dp(i,j)\)表示第\(i\)個正負符號到第\(j\)個連續符號段連著的那個數字有多少種添加括號的方法。

轉移的時候是枚舉最後一次運算時哪一個連續符號段的第一個(因為只有這一個是二元運算符

那麽就發現我們需要記錄一個從連續符號段的第一個到連續符號段的第一個正負符號的映射,記為\(st\)

然後從\(dp(i,k)\times dp(st_{k+1},j)\)轉移來。

這樣就三方出奇跡了。(%%% \(tourist\)

思路3:

這是\(shik\)的神奇記憶化搜索。

首先我們把原輸入變成以下段:

  • 連續數字:0
  • 正負(加減)符號:1
  • 乘除符號:2

那麽考慮\(dp(i,j)\)表示到了第\(i\)個段,打開的左括號有\(j\)個,有多少種方法。

然後考慮轉移。

假如這個位置是連續數字,那麽可以合上一些括號或者不合上。

否則就必須打開一個括號。

最後答案是\(dp(n,0)\)

(話說1和2只是用來判無解的。。。

思路4:

這是ACRush的神奇三方DP。

按照shik的方法分段。

直接考慮\(dp(i,j)\)表示從第\(i\)段到第\(j\)段的答案。

然後轉移的時候就是枚舉中間那一個字符的位置,然後左右答案乘起來一加就可以了。

思路5:

這是\(Al.cash\)的和\(shik\)差不多的方法。

兩人的狀態是一樣的,但是\(Al.cash\)用了前綴和來搞每次合上很多符號的操作對\(dp\)的影響。

思路6:

這是最難看懂的\(chenlijie\)神仙的方法。

首先把所有的連續符號段中的正負符號個數放到v數組中,

然後用一個\(dp\)\(vector\)存下所有的\(dp\)值,

從後往前枚舉v,對於每一個v,dp的前v+1個代表的是倒數的第*個正負字符到最後的答案。

然後把它們刪掉,後面的內容做一次前綴和就竟然可以轉移了!?

這。。。

感覺之前想的也不太對了。。。

待更。。。

思路7:

NuM的,基本同ACRush。

【Codeforces 115D】Unambiguous Arithmetic Expression