1176. Two Ends两人从两头取数

来源:互联网 发布:sql server 列转行 编辑:程序博客网 时间:2024/06/10 23:25
/*1176. Two Ends两人从两头取数题目大意:        给出n个正整数排成一列,A和B轮流取数,只能取两端的数,最后取到的数的和较大的人胜利,A和B之间的差为分值;        A可以自由选择策略,B的贪心策略取两端中较大的数,如果相等则取左边的数;        问A赢B的分值最大为多少。        n<=1000,且n为偶数。解题思路:        A尝试计算所有情况,并选出自己得分最多的情况;        计算所有情况时,减少重复计算(动态规划),每个状态为当前数列的左右端点位置。        4.重点:动态规划:出题点学习资料(背包九讲、百度搜索(有层次、PKU、ACM))*/#include <iostream>#include <stdlib.h>#include <algorithm>#include <memory.h>using namespace std;int dp[1000][1000];int a[1000];int fun(int left, int right){  if(left > right)    return 0;  //if(left == right)  //  return dp[left][right];  if(dp[left][right] != -1)    return dp[left][right];  //1.重点:动态规划,最容易出题点,但是题目很难理解   //选择左端,如果剩下的左端大则选择左端,否则选择右端,然后剩下的段再递归   int leftSum = a[left] + (a[left+1] >= a[right]? fun(left+2, right) : fun(left+1, right-1) );  //选择右端,如果剩下的左端大则选择左端,否则选择右端,然后剩下的段再递归   int rightSum = a[right] +(a[left] >= a[right-1]? fun(left+1, right-1): fun(left, right-2));    //2.重点:max函数   dp[left][right] = max(leftSum, rightSum);  return dp[left][right];}int main(){    int n = 0;    int count = 0;        while(1)    {      cin >> n;      if (n == 0)      break;         //3.重点:memset函数 (#include <memory.h>)       memset(dp,-1,sizeof(dp));            int Sum =0;      for(int i=0; i < n; i++)      {         cin >> a[i];         Sum = Sum+a[i];       }       int firstSum = fun(0,n-1);               count++;       cout << "In game " << count << ", the greedy strategy might lose by as many as "<<2*firstSum-Sum<<" points."<< endl;             }        //system("pause");       return 0;   }