hdu 4597 dp+前缀和+记忆化搜索

dp[i][i+len1][j][j+len2] = sum[i][len1+i][j][j+len2] -min { dp[i+1][i+len1][j][j+len2] , dp[i][i+len1-1][j][j+len2] , dp[i][i+len1][j+1][j+len2],dp[i][i+len1][j][j+len2-1]}

因为每个人都足够聪明,所以每个人作为先手时都会保证自己会得到最大受益,所以当前状态下的最大收益就是区间总和减去转换来的状态里收益最小的以获得最大的收益,有一点博弈的思想,故用四维的数组记录状态,然后用记忆化搜索进行搜索

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#define MAX 27
#define INF 9999999


using namespace std;

int a[MAX];
int b[MAX];
int dp[MAX][MAX][MAX][MAX];
int sum1[MAX];
int sum2[MAX];
int sum[MAX][MAX][MAX][MAX];

int dfs ( int l1 , int r1 , int l2 , int r2 )
{
    if ( dp[l1][r1][l2][r2] != -1 ) return dp[l1][r1][l2][r2];
    if ( l1 > r1 && l2 > r2 ) return dp[l1][r1][l2][r2] = 0;
    //l1>l2意味着这个序列中一个都没选的情况
    int sum = 0;
    int ans = 0;
    if ( l1 <= r1 ) sum += sum1[r1] - sum1[l1-1];
    if ( l2 <= r2 ) sum += sum2[r2] - sum2[l2-1];
    if ( l1 <= r1 )
       ans = max ( ans , sum - dfs(l1+1,r1,l2,r2) ),
       ans = max ( ans , sum - dfs(l1,r1-1,l2,r2) );
    if ( l2 <= r2 )
       ans = max ( ans , sum - dfs(l1,r1,l2+1,r2) ),
       ans = max ( ans , sum - dfs(l1,r1,l2,r2-1) );
    return dp[l1][r1][l2][r2] = ans;
} 

int main ( )
{
    int t,n;
    scanf ( "%d" , &t );
    while ( t-- )
    {
        scanf ( "%d" , &n );

        sum1[0] =  sum2[0] = 0;
        for ( int i = 1 ; i <= n ; i++ ) 
        {
            scanf ( "%d" , &a[i] );
            sum1[i] = sum1[i-1] + a[i];
        }

        for ( int i = 1 ; i <= n ; i++ )
        {
            scanf ( "%d" , &b[i] );
            sum2[i] = sum2[i-1] + b[i];
        }
        memset ( dp , -1 , sizeof ( dp ) );
        printf ( "%d\n" ,  dfs ( 1 , n , 1 ,n ) );        
    }
}


你可能感兴趣的:(C++,动态规划,记忆化搜索,区间DP)