您的位置:首页 > 其它

Uva 10891 Game of Sum - 区间DP..记忆化搜索

2013-07-31 13:48 344 查看
题意:

有一列数...A,B分别来取..每次只能从两头中一头开始拿走若干个..问最后A拿走的数比B拿走的大多少...

题解:

首先能想到是区间DP的问题...对于一个区间..感觉上是可以通过其子区间推出最优解的..

dp [ i ] [ j ] 代表在i,j区间能取得的最大值...

那么有 dp [ i ] [ j ] = sum [ i ] [ j ] - min ( dp [ i ] [ k ] , dp [ k ] [ j ] ) , ( i<=k<=j )

最后得出dp[ 1 ] [ n ] 代表了A能拿的最大价值.那么题目所需要的答案为 ans = dp[ 1 ] [n ] - ( sum [ 1 ] [ n ] - dp [ 1 ] [ n ] )

总结

所有的DP问题都可以用两种大方向来写: 1、递推 2、记忆化搜索

记忆化搜索的好处是十分直观....特别是对于树形DP和区间DP这类型的问题.

Program:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<algorithm>
#define ll long long
#define oo 1000000007
#define pi acos(-1.0)
#define MAXN 105
using namespace std;     
int n,sum[MAXN],dp[MAXN][MAXN];
bool used[MAXN][MAXN];
void dfs(int s,int e)  
{ 
      if (s>e) return;
      if (used[s][e]) return;  
      used[s][e]=true;
      dp[s][e]=-oo;
      int S=sum[e]-sum[s-1];  
      for(int k=1;k<=e-s+1;k++)
      {  
             dfs(s+k,e),dfs(s,e-k);
             dp[s][e]=max(dp[s][e],S-min(dp[s+k][e],dp[s][e-k]));  
      }  
      return;  
}  
int main()
{          
       while (~scanf("%d",&n) && n)
       {
              int i,x; 
              sum[0]=0;
              for (i=1;i<=n;i++) 
              {
                    scanf("%d",&x); 
                    sum[i]=sum[i-1]+x;
                    dp[i][i]=x;
              }
              memset(used,false,sizeof(used));
              dfs(1,n);   
              printf("%d\n",dp[1]
-(sum
-dp[1]
));
       }
       return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: