UVA 10891 Game of Sum(经典区间dp)

这道题的题意就是一段数字,两个人,每个人交替取数字,每次只能从左或者右取一个或者多个数字,保证自己拿到的数字之和最大,前提是两个人都足够聪明,那么,最后的差a-b等于多少。

思路就是: dp(i,i+k)表示的是在i~i+k中能得到的最大值,转移的思路是,在这一段中会分给两个人,所以dp[i][i+k]=sum[i][j]-min(dp[i][i+1].......... dp[i][i+k])就是找这中间所有的子序列中最少的就好

AC代码:

/* ***********************************************
Author        :yzkAccepted
Created Time  :2016/5/20 19:18:44
TASK		  :ggfly.cpp
LANG          :C++
************************************************ */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <stack>
using namespace std;
const int maxn=110;
const int inf=1<<27;
int a[maxn],A[maxn],dp[maxn][maxn];

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int n,i,j,k;
	while(~scanf("%d",&n)&&n)
	{
		memset(A,0,sizeof(A));
		for(i=0;i<=n;i++)
			for(j=0;j<=n;j++)
				dp[i][j]=-inf;
		for(i=1;i<=n;i++)
		{	scanf("%d",&a[i]);A[i]=A[i-1]+a[i];}
		for(i=1;i<=n;i++)
			dp[i][i]=a[i];
		for(k=1;k<n;k++)
		{
			for(i=1;i+k<=n;i++)
			{
				int sum=A[i+k]-A[i-1];
				for(j=i;j<i+k;j++)
					if(sum-dp[i][j]>dp[i][i+k])
						dp[i][i+k]=sum-dp[i][j];
				for(j=i+1;j<=i+k;j++)
					if(sum-dp[j][i+k]>dp[i][i+k])
						dp[i][i+k]=sum-dp[j][i+k];
				if(sum>dp[i][i+k])
					dp[i][i+k]=sum;
			}
		}
		printf("%d\n",2*dp[1][n]-A[n]);	
	}
    return 0;
}



你可能感兴趣的:(dp,uva)