2017组队训练赛11

来源:互联网 发布:linux编译命令 编辑:程序博客网 时间:2024/06/08 06:35

问题 B: 取数游戏2

时间限制: 1 Sec  内存限制: 128 MB
提交: 42  解决: 13
[提交][状态][讨论版]

题目描述

考虑一个由两个玩家玩的游戏。游戏开始前给定一串排成一排的N个数字。两位玩家轮流从这一串数中的最左端或者最右端取出一个数。当所有数字都被取完后,游戏结束。此时,两位玩家各自的得分将是他所有取出的数的和。得分较高的玩家获胜。
    假设你是先取者。请编写程序制定一个游戏的最佳策略。最佳策略是指这样一种数字取法,它能在最坏的情况(后取者的策略对自己最不利的情况)下得到最高的得分。

输入

 数据的第一行是一个正整数N,输入数据保证1<=N<=100。
第二行从左至右给出了游戏初始时的N个正整数。这些正整数保证不超过200。

输出

输出两个用空格隔开的正整数。他们分别表示游戏的先取者在最坏情况下最高的得分和此时后取者的得分。

样例输入

64 7 2 9 5 2

样例输出

18 11

提示



思路:当第一个人取数取到最后的时候可以分成两种情况:①还剩下一个数,则直接加上这个数即可,②还剩下两个数,取其中最大的数相加即可。


代码如下:

#include <bits/stdc++.h>using namespace std;int n,a[110],dp[110][110];int f(int l, int r){if(l == r) return a[l];if(r - l == 1) return max(a[l],a[r]);if(dp[l][r]) return dp[l][r];return dp[l][r] = max(a[l] + min(f(l+1,r-1),f(l+2,r)),a[r] + min(f(l+1,r-1),f(l,r-2)));//min()是因为两人的操作都是最优}int main(){while(~scanf("%d",&n)){int sum = 0;for(int i = 1; i <= n; i ++) scanf("%d",&a[i]), sum += a[i];memset(dp,0,sizeof(dp));int ans = f(1,n);printf("%d %d\n",ans,sum-ans);}return 0;}


原创粉丝点击