UVA 10891 区间DP+博弈思想

很明显带有博弈的味道。让A-B最大,由于双方都采用最佳策略,在博弈中有一个要求时,让一方的值尽量大。而且由于是序列,所以很容易想到状态dp[i][j],表示序列从i到j。结合博弈中的思想,表示初始状态i->j情况下,先手能获得的最大分数。后手能获得的就是sum[i][j]-dp[i][j]。接下来枚举先手选取的是两端的哪一段即可。

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int N=105;

int dp[N][N];
int sum[N][N];
int arr[N];

int main(){
	int n;
	while(scanf("%d",&n),n){
		memset(dp,0,sizeof(dp));
		for(int i=1;i<=n;i++)
		scanf("%d",&arr[i]);
		for(int i=n;i>=1;i--){
			for(int j=i;j<=n;j++)
			if(i==j) sum[i][i]=arr[i];
			else sum[i][j]=sum[i][j-1]+arr[j];
		}
/*		for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++)
		cout<<sum[i][j]<<" ";
		cout<<endl;
		}*/
		for(int i=n;i>=1;i--){
			for(int j=i;j<=n;j++){
				if(i==j) dp[i][j]=sum[i][j];
				else{
					int m=0;
					for(int k=i+1;k<=j;k++)
					m=min(dp[k][j],m);
					for(int k=j-1;k>=i;k--)
					m=min(dp[i][k],m);
					dp[i][j]=sum[i][j]-m;
				}
			}
		}
	/*			for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++)
		cout<<dp[i][j]<<" ";
		cout<<endl;
		}*/
		
		printf("%d\n",dp[1][n]-sum[1][n]+dp[1][n]);
	}
	return 0;
}

  

posted @ 2015-06-01 11:52  chenjunjie1994  阅读(167)  评论(0编辑  收藏  举报