题目:
取胜之道
Program国度的人,喜欢玩这样一个游戏,在一块板上写着一行数,共n个。两个游戏者,轮流从最右或最左取一个数。刚开始,每个游戏者的得分均为零。如果一个游戏者取下一个数,则将该数的值加到该游戏者的得分上,最后谁的得分最高谁就赢了游戏。给出这n个数( 从左往右), 假设游戏者都是非常聪明的,问最后两个人的得分(假设第一个人首先取数).
输入格式:第一行为n(2<=n<=100),第二行为n个数,每个数字之间均用空格隔开。输出为两个游戏者的得分.第一个数表示第一个游戏者的得分,第二个数为第二个游戏者的得分,两个数字之间用空格隔开。
如输入
6
4 7 2 9 5 2
输出
18 11
算法设计与分析: 让我们来考虑一下由于两个游戏者都是非常聪明的,也是意味着两个人都同样聪明,在同样的情况下会采用同样的策略。,那么该问题的意思是:如果确定了块板上写着一行数其两个游戏者的得分就是已经确定的了.首先我们想到回溯算法,我们容易得到该算法的是一个指数算法,其算法复杂度为:O(2^n),当n=100 时是不可解的.那么自然而然我们会想到动态规划算法。
算法的设计: 假设A(i,j)为第i个数到第j个数(i<=j)先取数游戏者的解,以此类推,后取数的游戏者的解为B(i, j),那么我们有:
A首先取第j个数,那么我们有:
A(i,j) = A(j,j) + B(i, j-1);//因为A先取了第j个数,那么由于剩下i到j-1数里A是后取的,那么就是充当B的角色。
B(i,j) = A(i,j-1);//因为A先取了第j个数,剩下的是i到j-1的数,那么B就用相当A的角色。
如果A不首先取第j个数,那么他肯定就是取第i个数,那么我们有:
A(i,j) = A(i,i) + B(i+1,j);//因为A先取了第i个数,那么在剩下i+1到j数里,它是充当B的角色
B(i,j) = A(i+1,j); //因为A先取了第i个数,那么在剩下i+1到j数里,它是充当A的角色
这里我们规定如果i>j, 则 A(i,j)=B(i,j)=0;
并假设块板上写着一行数保存在数据M[0..N]
算法的初始化:A(i,i) = M[i];B(i,i) = 0;
假设问题的规模为N,那么该算法复杂度为O(N^2)。
C++源码
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
#pragma once
#include <vector>
#include<iostream>
using namespace std;
class MethodOfWin
{
public:
MethodOfWin(void);
static pair<long,long> MaxAndMin(vector<int> M)
{
const int size_M = M.size();
vector< vector<int> > A(size_M);
vector< vector<int> > B(size_M);
for(int i=0; i< size_M ; ++i)
{
A[i] = vector<int>(size_M);
B[i] = vector<int>(size_M);
}
//初始化
for(int i=0; i<size_M; ++i)
for(int j=0; j<size_M; ++j)
{
A[i][i] = M[i];
B[i][i] = 0;
}
for(int l=2; l<=size_M; ++l)
for(int i=0;i<size_M-l+1;++i )
{
int k=i+l-1;
int temp_A1 = B[i][k-1] + M[k];
int temp_B1 = A[i][k-1];
int temp_A2 = M[i] + B[i+1][k];
int temp_B2 = A[i+1][k];
if(temp_A1>temp_A2)
{
A[i][k] = temp_A1;
B[i][k] = temp_B1;
}
else{
A[i][k] = temp_A2;
B[i][k] = temp_B2;
}
}
return make_pair(A[0][size_M-1], B[0][size_M-1]);
}
public:
virtual ~MethodOfWin(void);
};
int main(void)
{
vector<int> M(6);
M[0] = 4;
M[1] = 7;
M[2] = 2;
M[3] = 9;
M[4] = 5;
M[5] = 2;
pair<long,long> result = MethodOfWin::MaxAndMin(M);
cout<<result.first<<" "<<result.second<<endl;
return 1;