codeforces 448C C. Painting Fence(分治+dp)

题目链接:点击打开链接

题目大意:给出n个杆子,每个杆子有一个长度,每次可以刷一行或一列,问最少刷多少次可以将整个墙刷成黄色。

思路:首先我们能够想到,如果横着刷,为了得到最优解,当前刷的位置的下面也必须横着刷,然后对于每种情况都可以通过n次竖着刷得到整个黄色的墙。
所以我们采取分治的策略进行动态规划,也就是对于每个状态划分为两种情况讨论,如果要刷横向的话,最矮要刷到最矮的柱子的高度才可能得到比竖着刷优的解,然后就变成了多个具有相同性质的规模更小的墙,然后我们可以采取同样的策略进行分治,知道墙只有一根柱子的时候,可以直接通过一次竖着刷得到最优解,每次判断决策时采取先横着刷和直接竖着刷两种方案中较小的方案。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
const int maxn=5520;
int n;
long long dp[maxn][maxn];
long long num[maxn];
void solve(int l,int r,int h)
{
	int j;
	dp[l][r]=r-l+1;
	if(l==r)return ;
	long long  hh=10000000000;
	for(int i=l;i<=r;i++)
		hh=min(hh,num[i]);
	long long  ans=hh-h;//ans记录横着涂掉底层的步数
	for(int i=l;i<=r;i++)
	{
		if(num[i]==hh)continue;
		for(j=i;j<=r;j++)
		{
			if(j==r)break;
			if(num[j+1]==hh)break;
		}
		solve(i,j,hh);
		ans+=dp[i][j];
		i=j+1;
	}
	dp[l][r]=min(dp[l][r],ans);
}
int main()
{
   while(~scanf("%d",&n))
   {
		for(int i=1;i<=n;i++)
		{
			scanf("%I64d",&num[i]);
		}
		solve(1,n,0);
		printf("%I64d\n",dp[1][n]);
		memset(dp,0,sizeof dp);
   }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值