HDU1087(初识数位dp)

题目链接HDU1087
这道题难在他的思想上,作为入门数位dp的一道基础题并没什么难度,我借此机会写下自己对这题的理解。

动态规划最重要的是掌握他的思想,动态规划的核心思想是把原问题分解成子问题进行求解,也就是分治的思想。

解题思路:
创建数组 a 和数组dp,下标从 1 开始,dp[ i ]表示的是以下标为 i 的元素作为一小段数组的结尾的这段数组的最大值。
比如:dp[ 5 ] = { 1 , 3 , 4 , 2 , 5 } ,dp[ 2 ] 代表以 3 结尾的{1 , 3 }这样一段数组的最大值,因此dp[ 2 ] = 4。
当我们再求以 4 结尾的这段数组的最大值时,因为 4 > 3,满足升序的条件,棋子可以由1->3->4经过这个路径,所以求dp[ 3 ]时,只需把dp[ 2 ]和a[ 3 ]相加,有:dp[ 3 ] = dp[ 2 ] + a[ 3 ]
若 a[ 2 ] 和 a[ 3 ] 不满足升序,则要看前面的数是否可以a[ 1 ]是否可以和a[ 3 ]满足升序。

附上AC代码:

#include
#include
int main( void )
{
    int n , i , j ;
    int max , a [ 1005 ] , dp [ 1005 ] ;
    while( scanf( "%d" , &n ) != EOF && n != 0 )
    {
        memset( dp , 0 , 1005 * sizeof( dp [ 0 ] ) ) ;
        for( i = 1 ; i <= n ; i++ )
            scanf( "%d" , &a [ i ] ) ;
        dp [ 1 ] = a [ 1 ] ;

        for( i = 2 ; i <= n ; i++ )
            for( j = 1 ; j < i ; j++ )
            {
                if( a [ i ] > a [ j ] )
                {
                    if( dp [ j ] + a [ i ] > dp [ i ] )
                        dp [ i ] = dp [ j ] + a [ i ] ;
                }

                else
                    if( a [ i ] > dp [ i ] ) 
                        dp [ i ] = a [ i ] ;
            }

        max = 0 ;
        for( i = 1 ; i <= n ; i++ )
            if( max < dp [ i ] )
                max = dp [ i ] ;
        printf( "%d\n" , max ) ;
    }
    return 0 ;
}

你可能感兴趣的:(dp)