Codeforces 448C:Painting Fence 刷栅栏 超级好玩的一道题目
刷子只能是一个方向,可以竖着把一块板子都刷完,也可以横着把几块板子刷一节。问最少需要刷几次能把所有板子都刷完。
超级好玩的一道题,一开始二分着分治,发现有一些情况无法处理 01110 与11010,向上传递的时候,不知道是max还是求和。感觉这道题线段树也是可以做的。后来发现好玩的地方在于每次都找最小值那里切割就好了,然后每一轮都记录已经刷了的高度,最多就是区间长度,两者比较得出结果。
代码:
#include <iostream> #include <algorithm> #include <cmath> #include <vector> #include <string> #include <cstring> #pragma warning(disable:4996) using namespace std; int n; int val[5005]; int dfs(int ll, int r,int height)//前两个参数代表所要刷的区间,最后一个参数代表已经刷的高度 { //从最小值那里分治,而不是二分区间,这点没有想到 if (ll > r) return 0 ; int min_value = 1e9 + 7; int i, pos, sum;//记录当前区间的最小值和位置。然后看现在区间内有多少栅栏是大于所刷高度的,这个值就是最多刷的次数,即竖着刷 sum = 0; for (i = ll; i <= r; i++) { if (val[i] < min_value) { min_value = val[i]; pos = i; } if (val[i] > height) sum++; } int temp = min_value - height; return min(sum, dfs(ll, pos - 1, val[pos]) + dfs(pos + 1, r, val[pos]) + temp); } int main() { int i, res; scanf("%d", &n); for (i = 1; i <= n; i++) scanf("%d", val + i); res = min(n, dfs(1, n, 0)); printf("%d\n", res); //system("pause"); return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。