1. 程式人生 > >UVa 10891 Sum遊戲

UVa 10891 Sum遊戲

std input queue get 一個 href 兩個人 開始 lan

https://vjudge.net/problem/UVA-10891

題意:

有一個長度為n的整數序列,兩個遊戲者A和B輪流取數,A先取。每次玩家只能從左端或者右端取任意數量個數,但不能兩端都取。所有數都被取走後遊戲結束,然後統計每個人取走的所有數之和,作為各自的得分。兩個人采取的策略都是讓自己的得分盡量高,並且兩個人都足夠聰明,求A的得分減去B的得分後的結果。

思路:

不管是輪到誰取數,都是在一個序列中從左邊或右邊開始取最大值。

那麽我們就令d【i】【j】表示先手在【i~j】序列中所能取到的最大值。

狀態轉移時,枚舉從左端開始取k個數和從右端開始取k個數即可。

 1 #include<iostream>
 2
#include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<sstream> 6 #include<vector> 7 #include<stack> 8 #include<queue> 9 #include<cmath> 10 #include<map> 11 using namespace std; 12 typedef long long LL; 13 typedef pair<int
,int> pll; 14 const int INF=0x3f3f3f3f; 15 const int maxn=100+5; 16 17 int n; 18 int a[maxn]; 19 int sum[maxn]; 20 int vis[maxn][maxn]; 21 int d[maxn][maxn]; 22 23 int dp(int i,int j) 24 { 25 if(vis[i][j]) return d[i][j]; 26 vis[i][j]=1; 27 28 int m=0; 29 for(int k=i+1
;k<=j;k++) m=min(m,dp(k,j)); 30 for(int k=j-1;k>=i;k--) m=min(m,dp(i,k)); 31 d[i][j]=sum[j]-sum[i-1]-m; 32 return d[i][j]; 33 } 34 35 int main() 36 { 37 //freopen("D:\\input.txt","r",stdin); 38 while(~scanf("%d",&n) && n) 39 { 40 sum[0]=0; 41 for(int i=1;i<=n;i++) 42 { 43 scanf("%d",&a[i]); 44 sum[i]=sum[i-1]+a[i]; 45 } 46 47 memset(vis,0,sizeof(vis)); 48 printf("%d\n",2*dp(1,n)-sum[n]); 49 } 50 return 0; 51 }

UVa 10891 Sum遊戲