1. 程式人生 > 實用技巧 >CodeForces 448C. Painting Fence(搜尋)

CodeForces 448C. Painting Fence(搜尋)

題意:遊戲共有兩種操作
操作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;
}