POJ1887解题报告(最长下降子序列)

本文深入探讨了求解最长下降子序列问题的算法实现,包括递归表达形式(状态转移方程)的理解与应用,通过实例展示了如何利用状态转移方程解决实际问题,并提供了完整的代码实现。

题目说了很长,要求最长下降子序列。题目的输入比较奇怪,需要全部读入之后,再进行dp,否则会TLE(这是我看其他同学说的)。这个题目的递归表达形式(正规一点儿应该叫做:状态转移方程,我太土了)---状态转移方程为:

dp[i] = dp[j] + 1 (0 <= j < i, a[i] < a[j] && dp[i] <= dp[j])-----(1)

(1)中,dp[i]表示的是以第i个数字结尾的最长下降子序列的长度。其中,不好理解的是条件中的:dp[i] <= dp[j]。前半部分,还是比较好理解的,自己想想也能够想到,但是条件不太好想。dp[i] <= dp[j]这个体现的就是序列的含义。是由多个值组成的。要保证这些值是依次减小的。举例说明:

389,207,155,300,150,65 ------(2)

(2)中,再使用状态转移方程计算前四个值的时候,不考虑条件dp[i] <= dp[j],都是没问题的,但计算第五个值的时候,就出问题了。dp[1]=1 ,dp[2]=2,dp[3]=3,dp[4]=2,dp[5]=?当j=3的时候,dp[5]应该是4。当j=4的时候,如果不考虑条件dp[i] <= dp[j],则dp[5]应该是3,就不对了。
寻找状态转移方程很难,多用笔在纸上写写画画吧!
代码如下:  

#include 
#include 
using namespace std;

#define MAX 5001

int a[MAX], dp[MAX];
int main() {
	int index = 1;
	while (1) {
		int tmp;
		cin >> tmp;
		if (-1 == tmp) break;
		int len = 0;
		a[len++] = tmp;
		while(1) {
			cin >> tmp;
			if (-1 == tmp) break;
			a[len++] = tmp;
		}
		int max = 0;
		dp[0] = 1;
		if (dp[0] > max) max = dp[0];
		for (int i = 1; i < len; ++i) {
			dp[i] = 1;
			for (int j = 0; j < i; ++j) {
				if (a[i] < a[j] && dp[i] < dp[j] + 1)
					dp[i] = dp[j] + 1;
			}
			if (dp[i] > max) max = dp[i];
		}
		cout << "Test #" << index++ << ":" << endl;
		cout << "  maximum possible interceptions: " << max << endl;
		cout << endl;
	}
	return 0;
}

转载于:https://www.cnblogs.com/sing1ee/archive/2012/02/02/2765006.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值