POJ - 2955 Brackets https://vjudge.net/contest/369109#problem/C 括号匹配问题,注意是序列就可以,不一定要连续 dp主体:
for ( int k= 1 ; k<= len; k++ )
{
for ( int i= 0 ; i+ k< len; i++ )
{
for ( int j= i; j<= i+ k; j++ )
{
dp[ i] [ i+ k] = max ( dp[ i] [ j] + dp[ j+ 1 ] [ i+ k] , dp[ i] [ i+ k] ) ;
}
if ( ( s[ i] == '(' && s[ i+ k] == ')' ) || ( s[ i] == '[' && s[ i+ k] == ']' ) )
dp[ i] [ i+ k] = max ( dp[ i] [ i+ k] , dp[ i+ 1 ] [ i+ k- 1 ] + 1 ) ;
ans= max ( ans, dp[ i] [ i+ k] ) ;
}
}
#include <iostream>
#include <cstdio>
#include <string>
#include <string.h>
using namespace std;
int dp[ 150 ] [ 150 ] ;
string s;
int len;
int ans;
void Dp ( )
{
for ( int k= 1 ; k<= len; k++ )
{
for ( int i= 0 ; i+ k< len; i++ )
{
for ( int j= i; j<= i+ k; j++ )
{
dp[ i] [ i+ k] = max ( dp[ i] [ j] + dp[ j+ 1 ] [ i+ k] , dp[ i] [ i+ k] ) ;
}
if ( ( s[ i] == '(' && s[ i+ k] == ')' ) || ( s[ i] == '[' && s[ i+ k] == ']' ) )
dp[ i] [ i+ k] = max ( dp[ i] [ i+ k] , dp[ i+ 1 ] [ i+ k- 1 ] + 1 ) ;
ans= max ( ans, dp[ i] [ i+ k] ) ;
}
}
}
int main ( )
{
while ( cin>> s)
{
ans= 0 ;
if ( s[ 0 ] == 'e' )
break ;
memset ( dp, 0 , sizeof ( dp) ) ;
len= s. size ( ) ;
Dp ( ) ;
cout<< ans* 2 << endl;
}
return 0 ;
}
HDU4745 Two Rabbits https://vjudge.net/contest/369109#problem/B 寻找最长回文子序列问题 因为两只兔子一个顺时针运动,一个逆时针运动,而且是一个闭环,不可以重复越过,所以取两段最长回文子序列
#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
using namespace std;
int a[ 2500 ] ;
int f[ 1010 ] [ 1010 ] ;
int n;
int max ( int a, int b)
{
return a< b? b: a;
}
int main ( )
{
while ( scanf ( "%d" , & n) )
{
memset ( f, 0 , sizeof ( f) ) ;
if ( n== 0 )
break ;
for ( int i= 1 ; i<= n; i++ )
{
scanf ( "%d" , & a[ i] ) ;
f[ i] [ i] = 1 ;
}
for ( int k= 1 ; k<= n; k++ )
{
for ( int i= 1 ; i+ k<= n; i++ )
{
f[ i] [ i+ k] = max ( f[ i+ 1 ] [ i+ k] , f[ i] [ i+ k- 1 ] ) ;
if ( a[ i] == a[ i+ k] )
f[ i] [ i+ k] = max ( f[ i] [ i+ k] , f[ i+ 1 ] [ i+ k- 1 ] + 2 ) ;
}
}
int ans= 0 ;
for ( int i= 1 ; i<= n; i++ )
ans= max ( ans, f[ 1 ] [ i] + f[ i+ 1 ] [ n] ) ;
cout<< ans<< endl;
}
return 0 ;
}
CF245H Queries for Number of Palindromes https://vjudge.net/contest/369109#problem/D 给出L和R,找出L与R之间的回文串数目,注意这里如果s[5]=a,s[6]=a,5和6各算一个回文串。 dp[i][j]记录i到j是否满足回文串 f[i][j]记录i到j之间一共有多少个回文串
#include <iostream>
#include <cstdio>
using namespace std;
int dp[ 5500 ] [ 5500 ] ;
int f[ 5500 ] [ 5500 ] ;
char s[ 5500 ] ;
int t;
int l, r;
int len;
void DP ( )
{
len= strlen ( s+ 1 ) ;
for ( int i= 1 ; i<= len; i++ )
dp[ i] [ i] = 1 , f[ i] [ i] = 1 ;
for ( int k= 1 ; k<= len; k++ )
{
for ( int i= 1 ; i+ k<= len; i++ )
{
if ( k== 1 )
dp[ i] [ i+ k] = ( s[ i] == s[ i+ k] ) ;
else
dp[ i] [ i+ k] = dp[ i+ 1 ] [ i+ k- 1 ] && ( s[ i] == s[ i+ k] ) ;
if ( dp[ i] [ i+ k] )
f[ i] [ i+ k] + = 1 ;
f[ i] [ i+ k] + = f[ i+ 1 ] [ i+ k] + f[ i] [ i+ k- 1 ] - f[ i+ 1 ] [ i+ k- 1 ] ;
}
}
}
int main ( )
{
scanf ( "%s" , s+ 1 ) ;
scanf ( "%d" , & t) ;
DP ( ) ;
while ( t-- )
{
scanf ( "%d%d" , & l, & r) ;
printf ( "%d\n" , f[ l] [ r] ) ;
}
return 0 ;
}