USACO 5.1 Musical Themes(DP)
先写了暴力,过了10+组,后来想了想,发现这个跟求最长公共子序有点相似啊。改改了状态转移,wa在第2组,然后注意了一下,包含的情况,乱改的一下,就过了。。。
dp[i][j] 表示以i为结尾,j结尾最长的"主题"
1 /* 2 ID: cuizhe 3 LANG: C++ 4 TASK: theme 5 */ 6 #include <iostream> 7 #include <cstdio> 8 #include <cstring> 9 #include <queue> 10 #include <map> 11 #include <cmath> 12 #include <algorithm> 13 using namespace std; 14 int p[5011],o[5011]; 15 int dp1[6001]; 16 int dp2[6001]; 17 int Abs(int x) 18 { 19 return x > 0 ? x:-x; 20 } 21 int main() 22 { 23 int n,i,j,maxz; 24 freopen("theme.in","r",stdin); 25 freopen("theme.out","w",stdout); 26 scanf("%d",&n); 27 for(i = 0;i < n;i ++) 28 scanf("%d",&p[i]); 29 for(i = 1;i < n;i ++) 30 { 31 o[i] = p[i] - p[i-1]; 32 } 33 maxz = -1; 34 for(i = 1;i < n;i ++) 35 { 36 for(j = 1;j < n;j ++) 37 { 38 if(o[i] == o[j]) 39 dp2[j] = min(dp1[j-1]+1,max(Abs(j-i)-1,0));//乱改了一下。。 40 else 41 dp2[j] = 0; 42 } 43 for( j = 1;j < n;j ++) 44 { 45 dp1[j] = dp2[j]; 46 maxz = max(maxz,dp1[j]); 47 dp2[j] = 0; 48 } 49 } 50 if(maxz >= 4) 51 printf("%d\n",maxz+1); 52 else 53 printf("0\n"); 54 return 0; 55 }