题目说了很长,要求最长下降子序列。题目的输入比较奇怪,需要全部读入之后,再进行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;
}