題目鏈結
這道題與下一章的數字\(dp\)解題思路十分一致。
把尋找答案變成按位(並且是字典序從小到大)列舉當前這一位可以填的情況。
通過\(dp\)預處理的資訊告訴我們可行性,就可以把答案緊逼到乙個更小的(子)問題,非常有趣。
考慮 \(dp\) 預處理的資訊:
\(f[i][j][0 / 1]\) 表示 \(i\) 塊木板,最左邊的長度是第 \(j\) 小(排名為 \(j\) ),最左邊這塊是低位 / 高位的方案數。
由於木板的數量進行了變化,在加入一塊新的木板後,木板的值域從 \([1, i - 1]\) 變成了 \([1, i]\),所以我們可以考慮把木板的長度變為乙個相對的數量,從而進行轉化。
考慮第一種轉移
\(f[i][j][0] = \sum_^f[i - 1][k][1]\)
可以看做是把後面 \(i - 1\) 塊木板中真實長度 \(>= j\) 的再抬高一格,這樣再拼乙個 \(j\) 的木板就是乙個合適的狀態。
第二種轉移也類似:
\(f[i][j][1] = \sum_^ f[i - 1][k][0]\)
#include #include #include using namespace std;
const int n = 21;
typedef long long ll;
int n;
bool st[n];
ll c, f[n][n][2];
void init() }}
int main()
else c -= f[n][i][1];
if (f[n][i][0] >= c)
else c -= f[n][i][0];
} for (int i = n - 1; i; i--)
else c -= f[i][d][k];}}
} puts("");
} return 0;
}
ACWING309 裝飾圍欄(計數DP)
有 n 塊長方形的木板,長度分別為1,2,n,寬度都是1。現在要用這 n 塊木板組成乙個寬度為 n 的圍欄,滿足在圍欄中,每塊木板兩側的木板要麼都比它高,要麼都比它低。也就是說,圍欄中的木板是高低交錯的。我們稱 兩側比它低的木板 處於高位,兩側比它高的木板 處於低位。顯然,有很多種構建圍欄的方案。每...
acwing102 最佳牛圍欄
傳送門 二分答案,check函式主要方法就是,把所有的a i 先減去x,如果區間和是大於等於0的,也就是說這個區間的平均數大於x,從f開始,記錄前面的最小值,然後檢視是否存在答案。include using namespace std typedef long long ll define eps ...
AcWing 329 圍欄障礙訓練場
大型補檔計畫 題目鏈結 考慮模擬這個過程。f i 0 1 表示從第 i 個圍欄的 左 右端點開始往下走,走到原點的最小花費。轉移很容易想到,就是考慮找到乙個往下走第乙個碰到的圍欄 j j i 若沒有可以直接走到原點 然後 f i 0 1 min f j 0 1 d 考慮快速找到往下走最先遇到的圍欄,...