[Google] 9717 取数对弈
我写的Python代码:
class Solution(object):
def getNumberGame(self, n, nums):
m = len(nums)
dp = [[0] * m for j in xrange(m)]
for i in xrange(m):
dp[i][i] = nums[i] for i in reversed(xrange(0, n)):
for j in xrange(i + 1, m):
sum = self.getSum(i, j, nums)
dp[i][j] = sum - min(dp[i+1][j], dp[i][j-1]) total_sum = self.getSum(0, n - 1, nums) return dp[0][n-1], total_sum - dp[0][-1] def getSum(self, i, j, nums):
sum = 0
for k in xrange(i, j + 1):
sum += nums[k] return sum if __name__ == '__main__':
print Solution().getNumberGame(6, [4, 7, 2, 9, 5, 2])
转自: DustLeon
描述
取数对弈游戏问题: 取数游戏是一个 2 人对策游戏。游戏开始时将 n 个数在棋盘上从左到右排成一行。 甲乙双方轮流在这一行数的左右两端取数,直至全部取完 n 个数。每人所取得的数的总和为其得分值。 最后双方得分多者获胜。(游戏规定由甲方先取数。) 这里,甲乙双方都采用如下最优策略:
1)甲每次取都希望取到的这个数使自己得分最高
2)乙每次取都希望取到的这个数令甲的得分最低 请编程实现:在甲乙双方都采用最优策略的前提下,计算甲方先取数时双方的最后得分。
输入格式
对于每组输入数据,输入数据的第 1 行有 1 个正整数 n (1<=n<=100),表示有 n 个数在棋盘上从左到右排成一行。
接下来的 n 个数表示在棋盘上依次排列的 n 个数。
输出格式
在甲乙双方都采用最优策略的前提下,输出计算出的双方的最后得分。甲方得分在前,乙方得分在后。
输入样例
6
4 7 2 9 5 2
输出样例
18 11
Hint
注意:此题“贪心法”是不能保证总可行且最优的,因为你不能只“关注眼前”,而“不管以后”。 :) 1、前提和假设如下:
每次取数都只能从数列的头尾选择。甲乙双方都依最优策略来选择。(得分=所取的数之和)
sum(i,j):表示a[i]到a[j]的元素之和,即sum(i,j) = a[i]+...+a[j]
p[i][j]:表示从a[i]到a[j]时,甲方先取数并在甲乙双方都采用最优策略的前提下时,甲方的最终得分。 注意:这个“甲乙双方都采用最优策略的前提”,其实是甲乙双方都尽量使自己的得分最大。
对甲方是使自己得分最高这个动机好理解,对乙方而言,使得甲方得分最低为下步策略,由于总分是一定的,其实也就是使乙方自己得分最大。
因此,虽然有甲乙2个人对弈,但他们动机是一致的。 2、分析如下:
当甲方取a[i]时,p[i][j] = sum(i,j) - p[i+1][j];
当甲方取a[j]时,p[i][j] = sum(i,j) - p[i][j-1];
甲方会取这两种情况较大的作为自己的选择。即sum(i,j) - min( p[i+1][j], p[i][j-1] ) 3、递归关系如下:
1)当j=i, p[i][j] = a[i];
2)当j>i, p[i][j] = sum(i,j) - min( p[i+1][j], p[i][j-1] ) 4、题目所求为:
所求的甲方得分 = p[1][n]; 乙方得分 = sum - p[1][n] 5、例如:(左边界i,右边界j)
j=i 4 7 2 9 5 2
j=i+1 7 7 9 9 5
j=i+2 6 11 7 11
j=i+3 16 16 11
j=i+4 11 14
j=i+5 18
C++:
#include <iostream>
using namespace std; int p[101][101]; int sum(int i, int j) {
int sum_num = 0;
for(int r = i; r <= j; r ++)
sum_num += p[r][r];
return sum_num;
} int main()
{
int n;
int num[101];
cin >> n;
if(1 <= n && n <= 100) {
for(int i = 1; i <= n; i ++) {
cin >> num[i];
p[i][i] = num[i];
}
for(int j = 2; j <=n; j ++) {
for(int i =1; i <= n - j + 1; i ++) {
int r = j + i - 1;
p[i][r] = sum(i,r) - (p[i+1][r] < p[i][r-1] ? p[i+1][r] : p[i][r-1]);
}
}
cout << p[1][n] << " " << sum(1,n) - p[1][n];
}
return 0;
}
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std; int main()
{
int n,a[101],sum=0,m[101][101];
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
memset(m,0,sizeof(m));
for(int i=0;i<n;i++)
m[i][i]=a[i];
for(int i=n-1;i>=0;i--)
{
for(int j=i+1;j<n;j++)
{
sum=0;
for(int k=i;k<=j;k++)
sum+=a[k];
m[i][j] = sum-min(m[i+1][j],m[i][j-1]);
}
}
sum=0;
for(int k=0;k<=n-1;k++)
sum+=a[k];
printf("%d %d",m[0][n-1],sum-m[0][n-1]);
}
类似题目:
[LeetCode] 486. Predict the Winner 预测赢家
[Google] 9717 取数对弈的更多相关文章
- 洛谷P1288 取数游戏II[博弈论]
题目描述 有一个取数的游戏.初始时,给出一个环,环上的每条边上都有一个非负整数.这些整数中至少有一个0.然后,将一枚硬币放在环上的一个节点上.两个玩家就是以这个放硬币的节点为起点开始这个游戏,两人轮流 ...
- 洛谷P1288 取数游戏II
题目描述 有一个取数的游戏.初始时,给出一个环,环上的每条边上都有一个非负整数.这些整数中至少有一个0.然后,将一枚硬币放在环上的一个节点上.两个玩家就是以这个放硬币的节点为起点开始这个游戏,两人轮流 ...
- 【博弈论】【P1288】取数游戏II
传送门 Description 有一个取数的游戏.初始时,给出一个环,环上的每条边上都有一个非负整数.这些整数中至少有一个0.然后,将一枚硬币放在环上的一个节点上.两个玩家就是以这个放硬币的节点为起点 ...
- luoguP1288 取数游戏II [博弈论]
题目描述 有一个取数的游戏.初始时,给出一个环,环上的每条边上都有一个非负整数.这些整数中至少有一个0.然后,将一枚硬币放在环上的一个节点上.两个玩家就是以这个放硬币的节点为起点开始这个游戏,两人轮流 ...
- NOIP2007 矩阵取数游戏
题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. ...
- NOIP2007矩阵取数[DP|高精度]
题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. ...
- Vijos1451圆环取数[环形DP|区间DP]
背景 小K攒足了路费来到了教主所在的宫殿门前,但是当小K要进去的时候,却发现了要与教主守护者进行一个特殊的游戏,只有取到了最大值才能进去Orz教主…… 描述 守护者拿出被划分为n个格子的一个圆环,每个 ...
- codevs 1907 方格取数 3
Description 在一个有m*n 个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任意2 个数所在方格没有公共边,且取出的数的总和最大.试设计一个满足要求的取数算法. Input 第 ...
- HDU 1565&1569 方格取数系列(状压DP或者最大流)
方格取数(2) Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
随机推荐
- NISP二级笔记(二) 信息安全管理体系
- #505. 「LibreOJ β Round」ZQC 的游戏
题目描述 首先一定是让ZQC吃掉他能吃到的所有的球,这样才能尽可能的满足ZQC的质量是所有玩家中最大的. 在满足某一个玩家的质量不会超过ZQC的情况下,让这个玩家吃掉尽可能多的球,让其他玩家吃掉的尽可 ...
- C++2.0新特性(五)——<Rvalue_reference和move语义>
一.Rvalue_reference(右值引用)和move语义 1.左右值概念区分 左值:表达式结束后依然存在的对象,我们也叫做变量: 右值:表达式结束后就不存在的临时对象. 2.判断左值和右值 能对 ...
- 怎么用switchhost
第一步:打开exe, 第二部:在 My hosts 里面直接添加路径 106.75.131.183 npm.kuaizitech.cn 第三部 :打开my hosts 保护好眼睛,早睡早起,多运动,k ...
- 标准ACL详解
- js jquery 实现 排班,轮班,日历,日程。使用fullcalendar 插件
如果想用fullcalendar实现排班功能,或者日历.日程功能.那么只需要简单的几步: 这里先挂官网链接: fullcalendar fullcalendar官网下载链接 一.下载及简单配置 1.这 ...
- T-MAX--冲刺合集
目录 设想和目标 计划 资源 变更管理 设计/实现 测试/发布 团队的角色,管理,合作 总结 照片 各组员对于最终项目成果的贡献度 这个作业属于哪个课程 2019秋福大软件工程实践Z班 (福州大学) ...
- centos安装jdk1.8的三种方法
一.手动解压安装包: 1.在user目录下新建java文件夹: # cd /usr/ # mkdir java # cd java 2.下载jdk1.8,进入http://www.orac ...
- NGINX实现咏南跨平台中间件集群
NGINX实现咏南跨平台中间件集群 首先要开启咏南LINUX中间件. 1)编辑usr/local/nginx/conf/nginx.conf #user nobody;worker_processe ...
- keep-alive 实现从列表页到详情页,然后再回到列表页并保持原来列表页的页码数,并且只刷新数据
思路: keep-alive应用场景介绍 <keep-alive> 不会在函数式组件中正常工作,因为它们没有缓存实例.结合router,缓存部分页面 activated 和 deactiv ...