轮流取数

来源:互联网 发布:手卷钢琴软件 编辑:程序博客网 时间:2024/06/08 01:36

完美世界笔试题

题目描述:有一正整数序列,两个人小萌和BOSS轮流从序列的任意一端取数,取得的数累加到积分,知道取完所有的分数。两个人取数都是最优策略,问最后两人得分。
如: 4 7 2 9 52
最后得分为:18 11

解题思路:这题是个博弈问题,每取一个数需要使得对方在剩下的数中得分最少。可以使用动态规划求解,状态转换方程为:
maxScore[i][j] = max(sumOfPreN[j] - sumOfPreN[i - 1] - maxScore[i][j - 1],
sumOfPreN[j] - sumOfPreN[i - 1] - maxScore[i + 1][j]);
maxScore[i][j] 为i终点为j中先取的人能拿到的最大分数,sumOfPreN[j]为前j个数的和。

代码:

#include<iostream>#include<vector>#include<algorithm>using namespace std;int main(){    int n;    while (cin >> n)    {        vector<int> num(n + 1);        vector<int> sumOfPreN(n + 1);        vector<vector<int>> maxScore(n + 1, vector<int>(n + 1)); //保存i...j之间的所能得到的最大分数        for (int i = 1; i <= n; i++){            cin >> num[i];            sumOfPreN[i] = sumOfPreN[i - 1] + num[i];            maxScore[i][i] = num[i];        }        for (int i = n - 1; i > 0; --i)        {            for (int j = i + 1; j <= n; ++j)            {                maxScore[i][j] = max(sumOfPreN[j] - sumOfPreN[i - 1] - maxScore[i][j - 1],  //计算i到j之间的最大分数,思想是要使得拿出一个数后,后面取的从剩下的数组中得到的分数最少                        sumOfPreN[j] - sumOfPreN[i - 1] - maxScore[i + 1][j]);            }        }        cout << maxScore[1][n] << " " << (sumOfPreN[n] - maxScore[1][n]) << endl;    }}
0 0
原创粉丝点击