POJ 1390 Blocks 区间DP

本文深入探讨了区间动态规划的核心思想,即通过将大区间分解为小区间来寻找最优解。文章强调了设计优秀子结构的重要性,并通过实例解析了如何在不同题目中灵活运用这一策略。同时,提供了一个具体的区间DP代码示例,展示了如何处理子问题的决策变化和信息传递。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

区间DP的核心:把大区间分解成相同规模的小区间,小区间返回子结构的值给大区间从而得到最优解。但是怎么就能根据不同的题模拟出特定的比较合适的子结构呢?我觉得与其说这是一种编码的熟练度问题,不如说是对实际问题建模的敏感度问题。如何设计优秀的子结构问题真的很考验一个人的最基本最核心的创造力和分析能力。

就拿这个题来说,可以很轻易的想到dp[i][j]为i到j区间的最优值,但是在分解成子问题的时候发现决策变了。比如 1 2 3 1 2 3 1(就本题 拉长两倍 数量不变)的情况下 dp[1][7] 可以很明显的分解成 dp[1][4] 和 dp[5][7] 但是三个1明显是需要一起合并的,那么就需要把父结构的信息(比如最右侧的1 ) 传递给子结构,方案改成 dp[1][4] 和 dp[]5[6],把最右侧的1传递给4所在位置的len,递归解决的时候就得给父结构传个0过去,在加一维为父结构传递过来的需要合并的数量,初始化的时候父结构传个0过去即可

#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 2e2+10;
int dp[maxn][maxn][maxn],len[maxn],c[maxn],cnt;
int solve(int l,int r,int k)
{
	if(dp[l][r][k]) return dp[l][r][k];
	if(l==r) return (len[r]+k)*(len[r]+k);
	dp[l][r][k] = solve(l,r-1,0)+(len[r]+k)*(len[r]+k);
	for(int i = l; i < r; ++i) if(c[i]==c[r])
	dp[l][r][k] = max(dp[l][r][k],solve(l,i,len[r]+k)+solve(i+1,r-1,0));
	return dp[l][r][k];
}
int main()
{
	int cas = 0;
	int T; scanf("%d",&T);
	while(T--)
	{
		int pre = -1,cnt = 0;
		memset(len,0,sizeof(len));
		memset(dp,0,sizeof(dp));
		int n;scanf("%d",&n);
		for(int i = 1,x; i <= n; ++i)
		{
			scanf("%d",&x);
			if(x==pre) len[cnt]++;
			else
			{
				c[++cnt] = x; len[cnt]++; 
				pre = x;
			}
		}	
		printf("Case %d: %d\n",++cas,solve(1,cnt,0));
	}	
} 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值