「CSA49」Card Collecting Game

题目大意:有 \(n\) 种卡片,每种有 \(b_i\) 张,如果一个人集齐 \(k\) 张第 \(i\) 种卡片,那么其能获得的得分是 \(\lfloor\frac{k}{a_i}\rfloor \times c_i\) ,现在A要将所有卡片分成大小相同两堆,保证总卡片数量是偶数。A与B玩游戏,第一堆A先手轮流取,第二堆B先手轮流取,A要最大化自己的得分,B要最小化A的得分,求A能得到的最大得分。

解题思路:首先放在两堆的卡片都可以模 \(2a_i\) ,因为每 \(2a_i\) 双方必定都会各取 \(a_i\) 张取光得到 \(c_i\) 的贡献,对于剩下的部分,如果不足 \(2a_i-1\) ,那么不可能得到任何贡献 ,否则先手能得到 \(2a_i-1\) 的贡献,然后交换先后手。也就是说将每堆剩下 \(2a_i-1\) 的卡片按照 \(c_i\) 排序后,第一堆A能拿到 \(1,3,5..\) 种的贡献,第二堆A能拿到 \(2,4,6\) 种的贡献。然后就可以根据此设计 \(dp(i,j,x,y)\) 表示排完序后前 \(i\) 种卡片,放在第一堆共 \(i\) 张,当前第一堆中剩下 \(2a_i-1\) 的卡片摆了奇偶性为 \(x\) 堆,第二堆中摆了奇偶性为 \(y\) 堆,然后枚举当前这一种在第一堆种放多少计算贡献转移,复杂度是 \(O((\sum_{b_i})^2)\)。

实际上贡献只与当前该种卡片放到第一堆和第二堆中的数量除以 \(2a_i\) 的商和余数有关,商的部分无论怎样贡献都会被计算进去商-1份是常量,所以只需要考虑剩下的部分要放多少即可,但是这样的话就不能知道当前状态配上之前的常量能否凑成刚好两堆一样了,于是再对商的部分做一个多重背包判断,复杂度 \(O(\sum_{a_i}\sqrt{\sum_{b_i}}+(\sum_{a_i})^2)\)

code

/*program by mangoyang*/
#include<bits/stdc++.h>
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T & x){
int ch = 0, f = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
} const int N = 4005; bitset<250005> f;
int dp[2][8005][2][2], lim[N], tot[N], yu[N], sum, ans, sumA, n; struct Node{ int a, b, c; } s[N];
inline bool cmp(Node A, Node B){ return A.c > B.c; } inline void up(int &x, int y){ if(y >= x) x = y; } int main(){
read(n);
for(int i = 1; i <= n; i++)
read(s[i].a), read(s[i].b), read(s[i].c);
sort(s + 1, s + n + 1, cmp);
for(int i = 1; i <= n; i++){
lim[i] = (s[i].b < 2 * s[i].a) ? 0 : (s[i].b / (2 * s[i].a)) - 1;
yu[i] = s[i].b - 2 * s[i].a * lim[i], ans += s[i].c * lim[i];
tot[s[i].a] += lim[i], sum += s[i].b, sumA += yu[i];
}
f[0] = 1;
for(int i = 1; i <= 2000; i++)
for(int j = 1; j <= tot[i]; j <<= 1) f |= f << (j * 2 * i);
memset(dp, -1, sizeof(dp));
dp[0][0][0][0] = 0;
for(int i = 0, o = 0; i < n; i++, o ^= 1){
memset(dp[o^1], -1, sizeof(dp[o^1]));
for(int j = 0; j <= sumA; j++)
for(int a = 0; a < 2; a++)
for(int b = 0; b < 2; b++) if(~dp[o][j][a][b]){
for(int k = 0; k <= yu[i+1]; k++){
int ta = k, tb = yu[i+1] - k, tmp = ta / (2 * s[i+1].a) + tb / (2 * s[i+1].a);
int na = a, nb = b;
ta %= (2 * s[i+1].a), tb %= (2 * s[i+1].a);
if(ta == 2 * s[i+1].a - 1) tmp += (++na == 1);
if(tb == 2 * s[i+1].a - 1) tmp += (++nb == 2);
up(dp[o^1][j+k][na&1][nb&1], dp[o][j][a][b] + tmp * s[i+1].c);
}
}
}
int mx = 0;
for(int i = 0; i <= min(sum / 2, sumA); i++) if(f[sum/2-i]){
for(int a = 0; a < 2; a++)
for(int b = 0; b < 2; b++) mx = max(mx, dp[n&1][i][a][b]);
}
cout << mx + ans;
return 0;
}

「CSA49」Card Collecting Game的更多相关文章

  1. 「CSA49」Bunny on Number Line

    「CSA49」Bunny on Number Line 题目大意:有一个人从0开始走,每次可以向前走一步或者回到1,那么会产生一个位置序列,其中给出 \(k\) 个位置是好的.定义一个位置序列是好的, ...

  2. 「MoreThanJava」计算机发展史—从织布机到IBM

    「MoreThanJava」 宣扬的是 「学习,不止 CODE」,本系列 Java 基础教程是自己在结合各方面的知识之后,对 Java 基础的一个总回顾,旨在 「帮助新朋友快速高质量的学习」. 当然 ...

  3. 直播预告|App 首页如何动态化更新?来看蚂蚁技术专家详解「支付宝」全新卡片技术栈

    立即前往直播间预约观看 从icon到card,一场内容前置化的变革 从 Windows 时代开始,应用程序图标就成为了用户(流量)的主入口,一直持续到移动端时代. 图标即入口的方式,虽然足够方便但却不 ...

  4. 「译」JUnit 5 系列:条件测试

    原文地址:http://blog.codefx.org/libraries/junit-5-conditions/ 原文日期:08, May, 2016 译文首发:Linesh 的博客:「译」JUni ...

  5. 「译」JUnit 5 系列:扩展模型(Extension Model)

    原文地址:http://blog.codefx.org/design/architecture/junit-5-extension-model/ 原文日期:11, Apr, 2016 译文首发:Lin ...

  6. JavaScript OOP 之「创建对象」

    工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程.工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题. function createPers ...

  7. 「C++」理解智能指针

    维基百科上面对于「智能指针」是这样描述的: 智能指针(英语:Smart pointer)是一种抽象的数据类型.在程序设计中,它通常是经由类型模板(class template)来实做,借由模板(tem ...

  8. 「JavaScript」四种跨域方式详解

    超详细并且带 Demo 的 JavaScript 跨域指南来了! 本文基于你了解 JavaScript 的同源策略,并且了解使用跨域跨域的理由. 1. JSONP 首先要介绍的跨域方法必然是 JSON ...

  9. 「2014-5-31」Z-Stack - Modification of Zigbee Device Object for better network access management

    写一份赏心悦目的工程文档,是很困难的事情.若想写得完善,不仅得用对工具(use the right tools),注重文笔,还得投入大把时间,真心是一件难度颇高的事情.但,若是真写好了,也是善莫大焉: ...

随机推荐

  1. 【BZOJ】2154: Crash的数字表格 莫比乌斯反演

    [题意]给定n,m,求Σlcm(i,j),1<=i<=n,1<=j<=m,n,m<=10^7. [算法]数论(莫比乌斯反演) [题解] $$ans=\sum_{i\leq ...

  2. 从ZoomEye API 到 Weblogic 弱口令扫描

    参考资料: ZoomEye API: https://www.zoomeye.org/api/doc Weblogic-Weakpassword-Scnner: https://github.com/ ...

  3. c语言学习笔记.关键字.存储类型关键字等

    关键字const 1.修饰变量. 修饰的对象为常量,只读. 2.修饰指针. const 也可以和指针变量一起使用,这样可以限制指针变量本身,也可以限制指针指向的数据. const 离变量名近就是用来修 ...

  4. idea 控制台乱码

    第一步:修改intellij idea配置文件: 找到intellij idea安装目录,bin文件夹下面idea64.exe.vmoptions和idea.exe.vmoptions这两个文件,分别 ...

  5. 动态规划_01背包问题_Java实现

    原文地址:http://blog.csdn.net/ljmingcom304/article/details/50328141 本文出自:[梁敬明的博客] 1.动态规划 什么是动态规划?动态规划就是将 ...

  6. 33 - 并发编程-线程同步-Event-lock

    目录 1 线程同步 1.1 Event 1.1.1 什么是Flag? 1.1.2 Event原理 1.1.3 吃包子 1.2 Lock 1.2.1 lock方法 1.2.2 计数器 1.2.3 非阻塞 ...

  7. Spring Boot 在接收上传文件时,文件过大异常处理问题

    Spring Boot 在接收上传文件时,文件过大时,或者请求过大,spring内部处理都会抛出异常,并且捕获不到. 虽然可以通过调节配置,增大 请求的限制值. 但是还是不太方便. 之所以捕获不到异常 ...

  8. IndexWriterConfig的各个配置项说明(转)

    1.Analyzer:分析器 2.matchVersion:所用Lucene的版本 3.ramBufferSizeMB:随机内存 默认为16M. 用于控制buffer索引文档的内存上限,如果buffe ...

  9. Educational Codeforces Round 25 D - Suitable Replacement(贪心)

    题目大意:给你字符串s,和t,字符串s中的'?'可以用字符串t中的字符代替,要求使得最后得到的字符串s(可以将s中的字符位置两两交换,任意位置任意次数)中含有的子串t最多. 解题思路: 因为知道s中的 ...

  10. laravel5.1--数据库操作

    1 配置信息 1.1配置目录: config/database.php 1.2配置多个数据库 //默认的数据库 'mysql' => [ 'driver' => 'mysql', 'hos ...