线性dp以及区间合并详解

for (int i = s.size()-1; i>=0 ; i--)
{
	for (int j = i+1; j <s.size(); j++)
	{
		if (s[i] == s[j])
		{
			dp[i][j] = dp[i + 1][j - 1] + 2;
			ans = max(dp[i][j], ans);
		}
		else
		{
			dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);

		}
	}
}

如代码所示,这是一段求最长回文串的代码(注意最长回文串在原串中不一定是连续的)
通过这道题,我明白了以下几点

  1. dp问题一定要确保状态转移方程中等号右边的状态之前已经被更新了,这一点可以帮助我们确定for循环是正序还是逆序.

洛谷红名大佬的dp心得

1. 定义状态。
2. 写出状态转移式。
3. 根据状态转移式找出递推顺序。
4. 处理递推的边界。
5. 找出结果

做完洛谷提单相似基因问题的感悟
转移式通常只考虑最后一点
例如 线性dp中,如果只有一个序列,就靠当前序列i与i-1
如果有两个序列,就考虑a[i]和bj的关系有哪几种情况.
把情况列完一般状态转移方程就出来了;

区间dp:给定若干个闭区间,求最少多少个闭区间能够刚好囊括所有给出的闭区间

解法1:顶尖思路,

cnt表示走到这个点为止,与右区间抵消后的左区间还剩多少,如果是0,那么抵消之前是0,那么一定是答案区间的左端点,如果抵消之后是0,那么是右端点

for (int i = 1; i <= n; i++)
{
	int a, b;
	cin >> a >> b;
	x[a]++, b[y]++;
}
int cnt = 0;
for (int i = 1; i <= 1e6; i++)
{
	if (!cnt && x[i]) cout << i<<" ";
	cnt += x[i] - y[i];
	if (!cnt && y[i]) cout << i << endl;
}

解法二:合并区间,当需要开新区间时,就输出之前的begin和end

struct node //结构体存区间 
{
	int lo,hi;
}a[50000+10];
bool cmp(node a,node b) //排序 
{
	return a.lo<b.lo;
}
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i].lo>>a[i].hi;
	sort(a+1,a+n+1,cmp);
	st=a[1].lo;
	ov=a[1].hi; //答案区间初始化 
	for(int i=2;i<=n;i++)
	{
		if(a[i].lo>ov) //开新区间 
		{
			cout<<st<<" "<<ov<<endl;
			st=a[i].lo;
			ov=max(ov,a[i].hi);
		}
		else ov=max(ov,a[i].hi); //扩展原有区间 
		if(i==n) cout<<st<<" "<<ov<<endl; //注意点3 
	}
	return 0;
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值