zoj 3905(dp+滚动数组)
来源:互联网 发布:宜宾零距离网络论坛 编辑:程序博客网 时间:2024/05/03 09:17
Alice and Bob like eating cake very much. One day, Alice and Bob went to a bakery and bought many cakes.
Now we know that they have bought n cakes in the bakery. Both of them like delicious cakes, but they evaluate the cakes as different values. So they decided to divide those cakes by following method.
Alice and Bob do n / 2 steps, at each step, Alice choose 2 cakes, and Bob takes the cake that he evaluates it greater, and Alice take the rest cake.
Now Alice want to know the maximum sum of the value that she can get.
Input
The first line is an integer T which is the number of test cases.
For each test case, the first line is an integer n (1<=n<=800). Note that n is always an even integer.
In following n lines, each line contains two integers a[i] and b[i], where a[i] is the value of ith cake that Alice evaluates, and b[i] is the value of ith cake that Bob evaluates. (1<=a[i], b[i]<=1000000)
Note that a[1], a[2]..., a[n] are n distinct integers and b[1], b[2]..., b[n] are n distinct integers.
Output
For each test case, you need to output the maximum sum of the value that Alice can get in a line.
Sample Input
161 67 106 1112 1815 52 14
Sample Output
28
Author: HUA, Yiwei
Source: ZOJ Monthly, October 2015
#include<stdio.h>#include<string.h>#include<map>#include<algorithm>using namespace std;typedef long long ll;#define F first#define S second#define mod 1000000007const int INF = 1<<30;const int N = 810;int dp[N][N];pair<int,int> pr[N];bool cmp(pair<int,int> i, pair<int,int> j) {return i>j;}int main(){ int T, n; scanf("%d", &T); while(T--) { scanf("%d", &n); for(int i=1; i<=n; i++) scanf("%d%d", &pr[i].S,&pr[i].F); sort(pr+1,pr+n+1,cmp); //知道递推方程怎么来的就知道为什么要排序了 memset(dp, 0, sizeof(dp)); for(int i=1; i<=n; i++) { for(int j=1; j<=i/2; j++) { dp[i][j] = max(dp[i-1][j],dp[i-1][j-1]+pr[i].S); } } printf("%d\n", dp[n][n/2]); } return 0;}可以看到每层状态都是由上一层状态转移过来的,所以这里可以采用滚动数组减少一维空间,只需重复利用一维来进行操作。可以看到如果是二维的话,转移的过程并不会影响到上一层,而如果是一维的话: dp[j] = max(dp[j],dp[j-1]+...); 这样其实是有点问题的,问题在于更新 j 这个状态时其实是覆盖了相当于二维的上一层的 j 状态,那么在更新 j+1 这个状态时就不是由原来的 j 这个状态转移来的了。所以我们可以将循环的顺序调转一下,这样就不会有所影响了。
#include<stdio.h>#include<string.h>#include<map>#include<algorithm>using namespace std;typedef long long ll;#define F first#define S second#define mod 1000000007const int INF = 1<<30;const int N = 810;int dp[N];typedef pair<int,int> pii;pii pr[N];bool cmp(pii i, pii j) {return i>j;}int main(){ int T, n; scanf("%d", &T); while(T--) { scanf("%d", &n); for(int i=1; i<=n; i++) scanf("%d%d", &pr[i].S,&pr[i].F); sort(pr+1,pr+n+1,cmp); memset(dp, 0, sizeof(dp)); for(int i=1; i<=n; i++) { for(int j=i/2; j>=1; j--) { dp[j] = max(dp[j],dp[j-1]+pr[i].S); } } printf("%d\n", dp[n/2]); } return 0;}
- zoj 3905(dp+滚动数组)
- [ZOJ 3682] E - Cup 3 (背包DP计数 + 滚动数组)
- hdu 4576 Robot(dp+滚动数组)
- poj - 1036 - Gangsters(滚动数组dp)
- POJ3071-Football(概率DP+滚动数组)
- POJ-1018(DP+滚动数组)
- hdu 3392(滚动数组优化dp)
- poj 1036 Gangsters (DP:滚动数组)
- poj - 1159 - Palindrome(滚动数组dp)
- POJ-1297(DP + 滚动数组)
- POJ 1159 Palindrome(DP + 滚动数组)
- POJ1159 Palindrome(滚动数组DP)
- HDU 4576(概率DP+滚动数组)
- POJ1159回文字符串(DP+滚动数组)
- poj 1141(区间dp 滚动数组)
- poj1322 Chocolate(滚动数组dp)
- The Debut Album (dp + 滚动数组)
- poj1159 dp 滚动数组
- Windows平台下使用Jenkins自动发布Unity之Android程序与补丁
- perl与php之异同
- WebService实战(一)——实现第一个CXF
- 设计模式之观察者模式
- 在iOS开发中如何裁剪一个圆图像
- zoj 3905(dp+滚动数组)
- Unity 编辑器中获取GameView的分辨率
- Android中传递对象的三种方法以及Java对象的序列化和反序列化实践
- Android - Listener for incoming phone
- RGB、Lab、YUV、HSI、HSV等颜色空间的区别
- [TwistedFate]一维数组的声明,遍历以及数组元素的排序
- ListView布局、美化、点击
- 【Android产品质量提升系列】奇葩数据库与数据库差异引起的机型适配问题
- Android_AsyncTask学习