CSP-S/NOIP提高組 真題題解總結

Star_F發表於2024-10-02

DP:

  • 線性dp

    • P1091 [NOIP2004 提高組] 合唱隊形

      比較簡單的一道題。求出以 \(i\) 結尾的最長上升子序列和以 \(i\) 為頭的最長下降子序列,相加 \(-1\) 即可。

    • P1052 [NOIP2005 提高組] 過河

      如果不考慮 \(L\) 的範圍,那麼就是一道簡單的線性 dp 。

      但是 \(L\) 很大,石頭數量很少,所以每相鄰兩個石頭的空隙一定很大。

      前置知識:P3951 [NOIP2017 提高組] 小凱的疑惑

      給定兩個數 \(p\)\(q\) ,他們最大不能湊出的數是 \((p-1)(q-1)-1\) 。所以中間空隙過多一定是可以被湊出來的,即可以壓縮中間的空隙,然後線性 dp 即可。

    • P1006 [NOIP2008 提高組] 傳紙條

      求出 \(2\) 條從 \((1,1)\)\((n,m)\) 的路徑。重複只算一次,求最大路徑和。

      水題,不多贅述。記錄 \(dp_{A,B,C,D}\) 表示第一條走到 \((A,B)\) , 第二條走到 \((C,D)\) 。由於 \(A+B = C+D\) ,可以記錄他們的和,最佳化掉一維。

    • P1541 [NOIP2010 提高組] 烏龜棋

      記錄 \(dp_{A,B,C,D}\) 表示用了 \(A\)\(1\) 號卡片, \(B\)\(2\) 號卡片, \(C\)\(3\) 號卡片, \(D\)\(4\) 號卡片。

      暴力轉移即可 \(F_{A,B,C,D}=\max (F_{A-1,B,C,D},F_{A,B-1,C,D},F_{A,B,C-1,D},F_{A,B,C,D-1})+cost_{A+2B+3C+4D}\)

    • P2679 [NOIP2015 提高組] 子串

      字首和最佳化線性 dp。(推式子題)

      首先考慮如何 DP,然後再考慮如何最佳化。

      狀態表示:\(f_{i, j, k}\)表示只用 \(S\) 的前 \(i\) 個字母,選取了 \(k\) 段,可以匹配 \(T\) 的前 \(j\) 個字母的方案數。

      狀態計算:將 \(f_{i,j,k}\)表示的所有方案分成兩大類:

      • 不用 \(S_i\),則方案數是 \(f_{i-1,j,k}\)
      • 使用 \(S_i\),則方案數是 $ \sum f_{i-t,j-t,k-1}$,滿足 \(S_{i-t+1}=T_{i-t+1}\)\(t\) 從大到小列舉。

      時間複雜度是 $ \mathcal{O} (nm2k)$。

      我們發先 \(f_{i,j,k}\) 的第二項和 \(f_{i-1,j-1,k}\) 很像,可以考慮維護一個 \(tmp_{i,j,k}\)

      • \(S_i=T_j\) , \(tmp_{i,j,k}=tmp_{i-1,j-1,k}+f_{i-1,j-1,k-1}\)
      • \(S_i \neq T_j\)\(tmp_{i,j,k}=0\)

      (把式子展開可以發現 \(tmp\) 的規律)。

      然後空間會爆,寫滾動陣列或者 01揹包 倒序列舉最佳化掉第一維即可。

    • P5664 [CSP-S2019] Emiya 家今天的飯

      求解所有方案數

      \(f_{i,j}\) 表示前 \(i\) 種烹飪方式,做了 \(j\) 道菜的方案數。

      • 狀態轉移:
        \(i\) 種烹飪方式不做 \(f_{i,j}+= f_{i - 1,j}\)

      • \(i\) 種烹飪方法做 \(1\) 道主要食材是 \(k\) 的菜:\(f_{i,j} += f_{i-1,j-1} * a_{i, k}\)

      所有方案數量 $ A = \sum_{j = 1}^{n}f[n][j]$ 。

      求解不合法方案:

      \(dp_{i,j}\) 表示前 \(i\) 中烹飪方法,越界食材數 $ - $ 其他食材數 為 \(j\) 的方案數。

      狀態轉移:

      • \(i\) 種烹飪方法不選:\(dp_{i,j} += dp_{i-1,j}\)

      • 選越界食材 \(c\)\(dp_{i,j} += dp_{i-1,j-1} * a_{i, c}\)

      • 選其他食材 \(dp_{i,j} += dp_{i-1,j+1} * (s_i - a_{i, c})\)

      所有方案數量: $ B = \sum dp_{n,j} (j > 0)$ 。

      \(A-B\) 即可。

      時間複雜度 \(\mathcal{O}(n ^ 2m)\)

      \(Tips\)
      做差有可能為負數,把所有狀態加一個 \(+n\) 的偏移量即可。

    • 總結

      對於線性 dp的問題,一般狀態定義\(f_{前\ i\ 個,滿足 \ ....\ 狀態}\),狀態可能很多,所以可能有很多維。

      狀態轉移:考慮這個集合是由誰構成的,進行分類。比如分成 選 \(a\) 和不選 \(a\) ......

      最佳化:如果狀態過多,考慮滾動陣列或者揹包最佳化,轉移中有求和,求最值等考慮用字首和,單調佇列最佳化。

  • 區間dp

  • 揹包

  • 狀壓dp

  • 樹形dp

  • 倍增最佳化dp

貪心:

搜尋:

  • DFS

  • BFS

  • 剪枝

數學:

  • 數論:

  • 組合數學

圖論:

  • 拓撲排序

  • LCA

  • 最短路

  • 二分圖

資料結構:

  • 並查集

  • 線段樹

  • 單調佇列

基礎演算法:

  • 列舉

  • 模擬

  • 字串

  • 排序

  • 二分

  • 位運算

  • 構造

  • 雜湊

  • 找規律

相關文章