题目大意:给你n张牌,排成一排放在桌子上,可以从左端拿也可以从右端拿。现在有A,B两人轮流取牌,A先取,两人足够聪明,即都想取最大的牌总和,问A能取到的最大值。
解题思路:定义dp[i][j][k]。k只有0,1,表示在i->j这段区间内分别取左右两端能取到的最大总和。
#include<bits/stdc++.h> using namespace std; typedef long long INT; #define min(a,b) ((a)<(b)?(a):(b)) #define max(a,b) ((a)>(b)?(a):(b)) const int maxn=1e3+20; int dp[maxn][maxn][2]; int a[maxn]; int main(){ int n; while(scanf("%d",&n)!=EOF){ int sum=0; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); sum+=a[i]; } for(int i=1;i<=n;i++){ dp[i][i][0]=a[i]; dp[i][i][1]=a[i]; } for(int i=1;i<n;i++){ dp[i][i+1][0]=a[i]; dp[i][i+1][1]=a[i+1]; } int tm00,tm01,tm11,tm10; for(int k=2;k<n;k++){ for(int i=1;i+k<=n;i++){ tm00=a[i]+max(dp[i+2][i+k][0],dp[i+2][i+k][1]); tm01=a[i]+max(dp[i+1][i+k-1][0],dp[i+1][i+k-1][1]); dp[i][i+k][0]=min(tm00,tm01);//后手肯定会让先手这次只能取到上次取的两个最大值中的最小值 tm11=a[i+k]+max(dp[i][i+k-2][0],dp[i][i+k-2][1]); tm10=a[i+k]+max(dp[i+1][i+k-1][0],dp[i+1][i+k-1][1]); dp[i][i+k][1]=min(tm11,tm10); } } int tmp=max(dp[1][n][0],dp[1][n][1]); printf("%d\n",2*tmp-sum); } return 0; }
时间: 2024-10-10 13:53:39