CodeForces 448C. Painting Fence(搜尋)
阿新 • • 發佈:2020-07-15
題意:遊戲共有兩種操作
操作1,將其中一列的格子全部消除
操作2,選擇一個連續的區間,在這個區間裡,\(不存在某一列為空(已經被消除)\),然後讓這個區間的每一列都消除一格。
兩種操作花費都為1。
現在給出遊戲初始的樣子,請你計算通過這個遊戲的最小花費。
分析:搜尋做,對於一個區間來說,如果橫著減去每一格中的數,直到出現某一個格子為0,我們則不能粉刷了,然後再對於這個連續區間內的一些連續小區間進行粉刷,中間由於之前粉刷的原因而被0隔開。因此,我們可以遞迴處理這些因為0而隔開的小區間。
#include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; const int N = 5005; int a[N]; int dfs(int l, int r) { if (l > r) return 0; //只剩下一個子區間 if (l == r) { if (a[l] == 0) return 0; else return 1;//一次性消除,花費1 } int last = l - 1; int res = 0; //橫著消除每一格 int mn = a[l]; for (int i = l + 1; i <= r; ++i) mn = min(mn, a[i]); for (int i = l; i <= r; ++i) { a[i] -= mn; //出現0被隔開,遞迴處理之後的每個小區間 if (a[i] == 0) res += dfs(last + 1, i - 1), last = i; } res += dfs(last + 1, r); //另一種所有格子採用第一種操作的方案 return min(res + mn, r - l + 1); } int main() { int n; scanf("%d", &n); for (int i = 1; i <= n; ++i) scanf("%d", &a[i]); printf("%d\n", dfs(1, n)); return 0; }