[Topcoder]ZigZag(dp)
题目链接:https://community.topcoder.com/stat?c=problem_statement&pm=1259&rd=4493
题意:给一串数字,求出最长的波动序列。波动的定义是一个数相邻的两个数同时比他大或者同时比他小,形象的看成一个波动的三角函数吧。
定义dp(i)为到第i个数字时的最长波动序列长度,我们发现仅有一维的数组是存不下状态的,还应该再维护一个量,那就是第i个数字的时候他是波峰还是波谷。于是dp数组扩展成了dp(i,k),k可以取0或1分别表示是波峰还是波谷。更新的时候枚举第j(1~i-1)个数字,如果第i个数字和第j个数字不相同就更新,更新的时候要把i和j两个数字分别看成不同的极点。
1 #include <string> 2 #include <vector> 3 #include <sstream> 4 #include <algorithm> 5 #include <iostream> 6 #include <cstring> 7 8 using namespace std; 9 10 class ZigZag { 11 public: 12 int longestZigZag(vector<int> sequence) { 13 int dp[101010][2]; 14 int n = sequence.size(); 15 int a[101010]; 16 int ret = 0; 17 memset(dp, 0, sizeof(dp)); 18 for(int i = 1; i <= n; i++) a[i] = sequence[i-1]; 19 for(int i = 1; i <= n; i++) { 20 dp[i][0] = dp[i][1] = 1; 21 for(int k = 0; k < 2; k++) { 22 for(int j = 1; j <= i; j++) { 23 if(a[i] == a[j]) continue; 24 if(k == 0) { 25 if(a[i] < a[j]) dp[i][k] = max(dp[i][k], dp[j][!k]+1); 26 } 27 else { 28 if(a[i] > a[j]) dp[i][k] = max(dp[i][k], dp[j][!k]+1); 29 } 30 } 31 ret = max(ret, max(dp[i][0], dp[i][1])); 32 } 33 } 34 return ret; 35 } 36 };