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
", dfs(1, n));

	return 0;
}
原文地址:https://www.cnblogs.com/pixel-Teee/p/13307256.html