原题链接http://codeforces.com/contest/448/problem/C
题意大概是有n列篱笆,每列宽度都为1,高度为hi,现在有一把刷子宽度为1,每次刷不能改变方向,要么横着刷要么竖着刷,可以刷任意长度,但是方向不能改变,问最少刷多少次能把篱笆刷完。
仔细想一下,发现顶多刷n次就能够刷完,所以最多不会超过n次。而且如果某一列有横着刷的部分,那么下面都是横着刷的,(想一下如果下面是竖着刷,那上面就没有刷的 必要了),所以答案必定要么是某一列一整列都是横着刷的,(反证一下,如果每一列都不是一整列横着刷的,说明n列至少竖着刷了n次再加上横着的就已经>n了,显然不对的);要么当然还有可能是都是竖着刷,答案就是n了。
我们利用答案这个特性,可以想出一个dp状态,记dp[i][j]为前i列全部刷完后,第j列一整列都是横着刷的最小次数,
在h[1]前面加多一个h[0]= 0 ,表示一列都不横着刷的状态,
记minx(j,i)为h[j]到h[i]之间的最小值,
枚举j从0到i-1 如果h[i] <= minx(j , i-1) 那么说明第j列横着刷的可以延伸到第i列 那么dp[i][j] = dp[i-1][j] ;否则 dp[i][j] = dp[i - 1][j] + 1 (既然不能延伸到这里来那么干脆第i列竖着 刷)
dp[i][i] 的状态同样可以由前面转移得到,如果h[i] <= minx(j , i - 1)那么 dp[i][i] = dp[i-1][j] ; 否则 dp[i][i] = dp[i-1][j] + h[i] - minx ( j , i-1 )(这里表示需要重新再多横着刷几次)【这里注意,j同样是从0到i - 1 ,0也同样需要,代表一行都不横着刷时的状态 ,wa了好久就是因为没有从0开始枚举!!!】
下面是代码
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<set>
#include<map>
#include<time.h>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<iostream>
using namespace std;
#define LONG long long
const int INF=0x3f3f3f3f;
const int MOD=1e9+7;
const double PI=acos(-1.0);
#define clrI(x) memset(x,-1,sizeof(x))
#define clr0(x) memset(x,0,sizeof x)
#define clr1(x) memset(x,INF,sizeof x)
#define clr2(x) memset(x,-INF,sizeof x)
#define EPS 1e-10
using namespace std;
int minx[6000][6000];
int h[6000] ;
int dp[6000][6000];
int main()
{
int n ;
cin>> n;
h[0] = 0;
for(int i = 1; i<= n ; ++ i)
scanf("%d" ,&h[i]);
for(int i = 0; i <= n ; ++ i)
{
minx [i][i] = h[i];
for(int j = i + 1 ;j <= n ;++ j)
minx [i][j] = min(minx[i][j-1] , h[j]);
}
dp[1][1] = h[1];
dp[1][0] = 1;
for(int i = 2 ; i <= n ;++ i)
{
for(int j = 0 ; j < i ; ++ j)
{
if(h[i] <= minx[j][i-1] )
dp[i][j] = dp[i-1][j] ;
else
dp[i][j] = 1 + dp[i-1][j] ;
}
dp[i][i] = 0x3f3f3f3f;
for(int j = 0; j < i ;++ j)
{
if(h[i] <= minx[j][i] )
dp[i][i] = min (dp[i][i] , dp[i-1][j]);
else
dp[i][i] = min(dp[i][i] , dp[i-1][j] + (h[i] - minx[j][i]));
}
}
int ans = 0x3f3f3f3f;
for(int i = 0; i<= n ;++ i) ans = min(ans , dp[n][i]);
cout<<ans<<endl;
}

685

被折叠的 条评论
为什么被折叠?



