HiHo第173周 A Game 区间DP
来源:互联网 发布:淘宝号如何实名认证 编辑:程序博客网 时间:2024/05/29 16:58
- 样例输入
4-1 0 100 2
- 样例输出
99
描述
Little Hi and Little Ho are playing a game. There is an integer array in front of them. They take turns (Little Ho goes first) to select a number from either the beginning or the end of the array. The number will be added to the selecter's score and then be removed from the array.
Given the array what is the maximum score Little Ho can get? Note that Little Hi is smart and he always uses the optimal strategy.
输入
The first line contains an integer N denoting the length of the array. (1 ≤N ≤ 1000)
The second line contains N integers A1, A2, ... AN, denoting the array. (-1000 ≤Ai ≤ 1000)
输出
Output the maximum score Little Ho can get.
题意:有一个数组,小hi 和小ho要从中选一些数(小ho先选),规定只能选一头或一尾,问小ho能选的数的最大和。
题目分析:
1.枚举左右端点
每次轮到小Hi或者小Ho时,他们都面临同样的二选一决策:是拿走最左边的数,还是拿走最右边的数。
由于每次只能从数组首/尾拿走一个数,所以小Hi和小Ho在任何时候面对的残局都只可能是一段连续的子数组A[i..j]。我们不妨用dp[i][j]表示当面对A[i..j],先手最多能获得的得分。
如果我们能计算出所有f[i][j]的值,那么显然f[1][n]就是最终答案。
对于i < j的情况,先手P需要决策是拿走A[i]还是拿走A[j]?
如果拿走A[i],那么对手Q面对的是A[i+1 .. j],Q最多能获得的得分是dp[i+1][j]。而且Q一定会按照得到dp[i+1][j]这个得分的方式进行决策。所以先手P最大得分是sum(A[i .. j]) - f[i+1][j]。(A[i][j]的分数和减去P的得分)
同理如果拿走A[j],先手P最大得分会是sum(A[i .. j]) - f[i][j-1]。
由于此时先手P可以二选一,所以dp[i][j] = max{ sum(A[i .. j]) - dp[i+1][j], sum(A[i .. j]) - dp[i][j-1] }= sum(A[i .. j]) - min(dp[i+1][j], f[i][j-1])。
代码一种为递归一种为迭代
迭代:
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <map>#include <stack>using namespace std;const int maxn = 1010;int dp[maxn][maxn];int arr[maxn];int sum[maxn];int n;int main(){ while(scanf("%d", &n) != EOF) { memset(dp, 0, sizeof(dp)); memset(sum, 0, sizeof(sum)); for(int i = 1; i <= n; i++) { scanf("%d", &arr[i]); sum[i]=sum[i-1]+arr[i]; dp[i][i] = arr[i]; } for(int i = n; i >= 1; i--) { //从后往前最后才到达dp[1][n]; for(int j = i; j <= n; j++) { dp[i][j]=max(sum[j]-sum[i-1]-dp[i][j-1], sum[j]-sum[i-1]-dp[i+1][j]); } } printf("%d\n", dp[1][n]); } return 0;}
递归:
#include<bits/stdc++.h> using namespace std; int a[2000],d[1001][1001]; int v[1001][1001];//标记是否访问过 int dfs(int l,int r) { if(l>r)return 0; if(v[l][r])return d[l][r];//已经知道d[l][r] v[l][r]=1; d[l][r]=max(a[l]+min(dfs(l+2,r),dfs(l+1,r-1)),a[r]+min(dfs(l+1,r-1),dfs(l,r-2)));//因为小Hi不会让小Ho取得较大分数,所以中间用min return d[l][r]; } int main() { int n; scanf("%d",&n); memset(v,0,sizeof v); for(int i=1;i<=n;i++)scanf("%d",&a[i]); cout<<dfs(1,n)<<endl; }
2.枚举长度和起点
#include<bits/stdc++.h> using namespace std; const int maxn=1100; int n,m,dp[maxn][maxn],a[maxn],sum[maxn]; int main() { int i,j,k,t; scanf("%d",&n); for(i=1;i<=n;i++) scanf("%d",&a[i]),dp[i][1]=a[i],sum[i]=sum[i-1]+a[i]; for(i=2;i<=n;i++) //长度 { for(j=1;j+i-1<=n;j++) //起点 { dp[j][i]=max(sum[j+i-1]-sum[j-1]-dp[j][i-1],sum[j+i-1]-sum[j-1]-dp[j+1][i-1]); } } printf("%d\n",dp[1][n]); return 0; }
- hiho第173周 A Game (区间DP)
- HiHo第173周 A Game 区间DP
- hiho一下 第173周 题目1 : A Game 【区间dp】
- A Game hiho一下第173周
- hihocoder A Game 区间dp
- hiho一下 第109周 Tower Defense Game 树DP+贪心
- 【区间问题】 hiho一下第152周
- hihoCode #1338 : A Game (区间dp)
- hiho一下 第113周 Fibonacci (dp)
- hiho一下 第109周:Tower Defense Game
- USACO-Section 3.3 A Game (区间DP)
- Codeforces 327A Flipping Game(区间DP,暴力枚举)
- hiho一下第137周《建造基地》DP
- hiho一下 第137周-建造基地(背包dp)
- hiho一下 第158周 非法二进制数 (dp)
- lightoj1031 - Easy Game【区间dp】
- hiho 第177周
- hiho一下 第143周 hiho密码
- 网络架构遵循原则
- mac mamp pro+phpStorm+Xdebug配置和断点调试
- 完全数
- 标准C语言第十天
- JavaScript把&转换为&
- HiHo第173周 A Game 区间DP
- Jzoj4790 选数问题
- 生活日记2017年10月26日
- 计算两个非负整数的最大公约数
- JAVA打印乘法表
- JavaScript的Date(动态显示时间)
- 使用Visual Studio Code搭建TypeScript开发环境
- Python 安装numpy+scipy+matlotlib
- NumPy库入门