Predict the winner

来源:互联网 发布:淘宝怎样免费开店 编辑:程序博客网 时间:2024/06/05 20:53

1 问题描述
Given an array of scores that are non-negative integers. Player 1 picks one of the numbers from either end of the array followed by the player 2 and then player 1 and so on. Each time a player picks a number, that number will not be available for the next player. This continues until all the scores have been chosen. The player with the maximum score wins.

Given an array of scores, predict whether player 1 is the winner. You can assume each player plays to maximize his score.

2例子说明
Example 1:
Input: [1, 5, 2]
Output: False
Explanation: Initially, player 1 can choose between 1 and 2.
If he chooses 2 (or 1), then player 2 can choose from 1 (or 2) and 5. If player 2 chooses 5, then player 1 will be left with 1 (or 2).
So, final score of player 1 is 1 + 2 = 3, and player 2 is 5.
Hence, player 1 will never be the winner and you need to return False.

Example 2:
Input: [1, 5, 233, 7]
Output: True
Explanation: Player 1 first chooses 1. Then player 2 have to choose between 5 and 7. No matter which number player 2 choose, player 1 can choose 233.
Finally, player 1 has more score (234) than player 2 (12), so you need to return True representing player1 can win.

3解决思路

使用动态规划(DP)来解决这个问题。思路:
题目的要求等价于第一个玩家最后选择的分数之和能否达到全部分数之和的一半以上。
DP(i,j)表示某个player需要在原序列第i个元素到第j个元素这个序列所能选择到的最多分数。Sum(i,j)表示第i个元素到第j个元素分数之和。Nums表示原序列。
在DP(i,j)时刻该玩家只能选择第i个和第j个元素。
如果选择第i个元素,那么该玩家将获得分数:
DPL(i,j)=Nums[i]+Sum(i,j)-DP(i+1,j)
如果选择第j个元素,那么该玩家将获得分数:
DPR(i,j)=Nums[j]+Sum(i,j)-DP(i,j-1)
因此该玩家会选择使得DP(i,j)更大那个元素。因此有
DP(i,j)=max{DPL,DPR}。

4 代码实现

#include "stdafx.h"#include<vector>#include<iostream>#include<algorithm>using namespace std;bool solution(const vector<int> & nums){    vector<vector<int>> score(nums.size(), vector<int>(nums.size()));    vector<int> preSums(nums.size() + 1);    preSums[0] = 0;    for (unsigned int i = 1; i < preSums.size(); i++)    {        preSums[i] = preSums[i - 1] + nums[i - 1];    }    for (int unsigned len = 1; len <= nums.size(); len++){        for (int unsigned lhs = 0; lhs + len - 1 < nums.size(); lhs++){            int rhs = lhs + len - 1;            if (rhs == lhs){                score[lhs][rhs] = nums[rhs];            }            else if (lhs == rhs - 1){                score[lhs][rhs] = max(nums[lhs],nums[rhs]);            }            else {                int leftscore = nums[lhs] + preSums[rhs + 1] - preSums[lhs + 1] - score[lhs + 1][rhs];                int rightscore = nums[rhs] + preSums[rhs] - preSums[lhs] - score[lhs][rhs - 1];                score[lhs][rhs] = max(leftscore, rightscore);            }        }    }    return score[0][nums.size() - 1] >= preSums[nums.size()] / 2 + preSums[nums.size()] % 2;}int _tmain(int argc, _TCHAR* argv[]){       vector<int> iv;    iv.reserve(50);    int i;    while(cin>>i){         iv.push_back(i);    }    if (solution(iv)){        cout << "True" << endl;    }    else        cout << "False" << endl;    return 0;}

这里写图片描述
这里写图片描述
这里写图片描述

5总结
该算法的时间复杂度为O(n*n)。DP思想在这里体现为维护一个矩阵,将大规模的问题转化为比它小的已经解决的问题。这跟斐波那契数列使用一个数组来记录已经解决的值得思想类似。此问题应该也可以使用递归方法解决,复杂度可能会更高。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 离婚有贷款的房子怎么办 买房没过户房主反悔怎么办 房子过户卖方爱人去世怎么办 黄浦区学生社会实践护照掉了怎么办 北京医保卡坏了怎么办 去了越南的签证怎么办 护照签证到期还在国外怎么办 办护照预约满了怎么办 未满16岁怎么办护照 办理护照采集指纹录不上怎么办 办理护照时指纹没有怎么办 未满16岁的怎么办护照 身份证照得太丑怎么办 武汉江夏怎么办健康证 小孩偏胖肚子大怎么办 手机安全中心密码忘记了怎么办 进京证一年12次怎么办 青霉素和头孢都过敏怎么办 手汗孢疹肿胀怎么办能吃消炎药吗 手机上办进京证怎么办 杭州公共自行车还车点满了怎么办 法院判决书下来对方不给钱怎么办 抓进看守所的人怎么办 在拘留所里病重抢救怎么办 昆明公租房户型确认后怎么办 18年工作好难找怎么办 我没工作了怎么办2018 婚姻质量差不幸福该怎么办 吸毒犯戒毒所不收怎么办 信用卡到期人进拘留所怎么办? 人在拘留所信用卡逾期怎么办 探视权不让接走怎么办 医保过了缴费期怎么办 充电宝充手机慢怎么办 执行局执行不到钱怎么办 小孩挖耳朵疼了怎么办 挖耳朵挖破了怎么办 挖耳朵皮挖破了耳鸣怎么办 北京自考证丢啦怎么办 不服检察院的答复函该怎么办 检察院控申答复函不复怎么办