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; }