/*
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;
}
1176. Two Ends两人从两头取数
最新推荐文章于 2022-02-26 23:34:49 发布