UVA-12260-Free Goodies
2017-10-11 17:17
253 查看
ACM模版
首先我们按照 Petra 的贪心策略进行排序,然后分析可以发现(假定先手是 Jan),Jan 的操作无非两种,一种是拿 Petra 下次要取的糖果,另一种就是拿别的,简单的说就是抢与不抢的问题,而前 i 个糖果,Jan 最多抢到 i+12 个糖果。所以我们设 dp[i][j] 表示前 i 个糖果,Jan 抢夺 j 个的最大值。
这里并没有结束,因为我们还要保证 Petra 的价值尽量大,所以可以考虑的是,先设所有糖果 x 之和为 sum,Jan 每取一个糖果,Petra 就损失对应的 x,我们考虑为这次操作的花费,只要在保证自己价值最大的情况下,花费尽量小即可,也就是再维护一个 cost[][] 即可。
另外,如果先手是 Petra,自然是没有争议,毕竟是贪心嘛,所以直接从序列第二个开始考虑即可,默认第一个被 Petra 贪心取走了。
很巧妙的贪心与动归的结合问题,刘汝佳老师好像说这个题可以完全贪心搞,有些懵,不是特别了解怎么搞……当然,上述题解的代码并没有体现出来多少贪心部分,可能这个题思路上是贪心和动归的结合,但是解法上可以只用贪心或者只用动归就能解决。
描述
题解
Petra 和 Jan 轮流取糖果,每个糖果有 x 和 y 两个属性,Petra 取则获得 x 价值,Jan 取则获得 y 价值。Petra 贪心策略取每次取 x 价值最大,如果 x 相同则取 y 价值最小,Jan 则是为了达到最终状态为自己价值最大,并且对手的价值尽量大。首先我们按照 Petra 的贪心策略进行排序,然后分析可以发现(假定先手是 Jan),Jan 的操作无非两种,一种是拿 Petra 下次要取的糖果,另一种就是拿别的,简单的说就是抢与不抢的问题,而前 i 个糖果,Jan 最多抢到 i+12 个糖果。所以我们设 dp[i][j] 表示前 i 个糖果,Jan 抢夺 j 个的最大值。
这里并没有结束,因为我们还要保证 Petra 的价值尽量大,所以可以考虑的是,先设所有糖果 x 之和为 sum,Jan 每取一个糖果,Petra 就损失对应的 x,我们考虑为这次操作的花费,只要在保证自己价值最大的情况下,花费尽量小即可,也就是再维护一个 cost[][] 即可。
另外,如果先手是 Petra,自然是没有争议,毕竟是贪心嘛,所以直接从序列第二个开始考虑即可,默认第一个被 Petra 贪心取走了。
很巧妙的贪心与动归的结合问题,刘汝佳老师好像说这个题可以完全贪心搞,有些懵,不是特别了解怎么搞……当然,上述题解的代码并没有体现出来多少贪心部分,可能这个题思路上是贪心和动归的结合,但是解法上可以只用贪心或者只用动归就能解决。
代码
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAX_LEN_NAME = 11; const int MAXN = 1010; struct Node { int x, y; bool operator < (const Node &rhs) const { if (x != rhs.x) { return x > rhs.x; } return y < rhs.y; } } arr[MAXN]; int n; int dp[MAXN][MAXN >> 1]; int cost[MAXN][MAXN >> 1]; char name[MAX_LEN_NAME]; int main() { int T; scanf("%d", &T); while (T--) { scanf("%d%s", &n, name); int sum = 0; for (int i = 1; i <= n; ++i) { scanf("%d%d", &arr[i].x, &arr[i].y); sum += arr[i].x; } sort(arr + 1, arr + 1 + n); memset(dp, 0, sizeof(dp)); memset(cost, 0, sizeof(cost)); int cur = 0; int i = name[0] == 'P' ? 2 : 1; for (; i <= n; ++i) { ++cur; int t = (cur + 1) >> 1; for (int j = 1; j <= t; ++j) { int &ans = dp[i][j] = dp[i - 1][j]; cost[i][j] = cost[i - 1][j]; if (j == 1 || dp[i - 1][j - 1]) { int tmp = dp[i - 1][j - 1] + arr[i].y; if (tmp > ans) { ans = tmp; cost[i][j] = cost[i - 1][j - 1] + arr[i].x; } else if (tmp == ans) { cost[i][j] = min(cost[i][j], cost[i - 1][j - 1] + arr[i].x); } } } } printf("%d %d\n", sum - cost [(cur + 1) >> 1], dp [(cur + 1) >> 1]); } return 0; }
相关文章推荐
- UVA 12260 - Free Goodies(dp+贪心)
- uva 12260 - Free Goodies (dp,贪心 | 好题)
- UVA - 12260 Free Goodies
- Free Goodies - UVa 12260 dp
- UVA 12260 Free Goodies (DP)
- UVA - 12260 Free Goodies(dp比较难想到)
- uva 12260 - Free Goodies(dp+贪心)
- uva12260 - Free Goodies 贪心+dp
- uva 12260 - Free Goodies (dp,贪心 | 好题)
- uva 12260 Free Goodies DP+一点点贪心
- uva 12260(dp)
- uva12260(DP)
- UVALive 4945 Free Goodies
- Free Goodies UVA - 12260
- UVA 12260 (思路dp)
- UVALive 4945 Free Goodies
- uva 11542 Square 高斯消元变形+异或消元
- uva 11549 - Calculator Conundrum(模拟)
- UVA11100_旅行
- UVA 540 Team Queue