「CSA49」Card Collecting Game
「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的更多相关文章
- 「CSA49」Bunny on Number Line
「CSA49」Bunny on Number Line 题目大意:有一个人从0开始走,每次可以向前走一步或者回到1,那么会产生一个位置序列,其中给出 \(k\) 个位置是好的.定义一个位置序列是好的, ...
- 「MoreThanJava」计算机发展史—从织布机到IBM
「MoreThanJava」 宣扬的是 「学习,不止 CODE」,本系列 Java 基础教程是自己在结合各方面的知识之后,对 Java 基础的一个总回顾,旨在 「帮助新朋友快速高质量的学习」. 当然 ...
- 直播预告|App 首页如何动态化更新?来看蚂蚁技术专家详解「支付宝」全新卡片技术栈
立即前往直播间预约观看 从icon到card,一场内容前置化的变革 从 Windows 时代开始,应用程序图标就成为了用户(流量)的主入口,一直持续到移动端时代. 图标即入口的方式,虽然足够方便但却不 ...
- 「译」JUnit 5 系列:条件测试
原文地址:http://blog.codefx.org/libraries/junit-5-conditions/ 原文日期:08, May, 2016 译文首发:Linesh 的博客:「译」JUni ...
- 「译」JUnit 5 系列:扩展模型(Extension Model)
原文地址:http://blog.codefx.org/design/architecture/junit-5-extension-model/ 原文日期:11, Apr, 2016 译文首发:Lin ...
- JavaScript OOP 之「创建对象」
工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程.工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题. function createPers ...
- 「C++」理解智能指针
维基百科上面对于「智能指针」是这样描述的: 智能指针(英语:Smart pointer)是一种抽象的数据类型.在程序设计中,它通常是经由类型模板(class template)来实做,借由模板(tem ...
- 「JavaScript」四种跨域方式详解
超详细并且带 Demo 的 JavaScript 跨域指南来了! 本文基于你了解 JavaScript 的同源策略,并且了解使用跨域跨域的理由. 1. JSONP 首先要介绍的跨域方法必然是 JSON ...
- 「2014-5-31」Z-Stack - Modification of Zigbee Device Object for better network access management
写一份赏心悦目的工程文档,是很困难的事情.若想写得完善,不仅得用对工具(use the right tools),注重文笔,还得投入大把时间,真心是一件难度颇高的事情.但,若是真写好了,也是善莫大焉: ...
随机推荐
- [bzoj 2460]线性基+贪心+证明过程
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2460 网上很多题目都没说这个题目的证明,只说了贪心策略,我比较愚钝,在大神眼里的显然的策略 ...
- 【译】第四篇 SQL Server代理配置数据库邮件
本篇文章是SQL Server代理系列的第四篇,详细内容请参考原文. 正如这一系列的前几篇所述,SQL Server代理作业是由一系列的作业步骤组成,每个步骤由一个独立的类型去执行.SQL Serve ...
- 使用npm安装包失败的解决办法(使用npm国内镜像介绍)
镜像使用方法(三种办法任意一种都能解决问题,建议使用第三种,将配置写死,下次用的时候配置还在): 1.通过config命令 npm config set registry https://regist ...
- 多维数组的字符依次输出,用python实现
#-*- coding=utf-8 -*-listm=["s","l","z","x","l",&q ...
- 爬行百度标题&URL案例
思路: 先将需要获取的匹配出,然后可以用"永真"(即while True:)来遍历使得URL可以一直自增变化(百度点击下一页URL的pn参数就增加10)每增加10就爬行一遍URL然 ...
- mac 上使用octave的plot错误的解决办法
在mac10.10上使用octave的时候,键入 plot(x, y)的时候会出现如下错误: ^ line : unknown or ambiguous terminal type; type jus ...
- Maven整合Spring与Solr
首先,在maven的pom.xml文件中配置对spring和solrj客户端的依赖: <project xmlns="http://maven.apache.org/POM/4.0.0 ...
- ASP连接读写ACCESS数据库实例(转)
(一) 数据库的选择:有许多的数据库你可以选择,SQL SERVER.ACCESS(*.mdb).EXCEL(*.xls).FOXPRO(*.dbf)甚至普通的文本文件(*.txt)都可以达到存储 ...
- HDU 2894 DeBruijin (数位欧拉)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2894 题目大意:旋转鼓的表面分成m块扇形,如图所示(m=8).图中阴影区表示用导电材料制成,空白区用绝 ...
- DNS使用TCP还是UDP?
DNS同时占用UDP和TCP端口53是公认的,这种单个应用协议同时使用两种传输协议的情况在TCP/IP栈也算是个另类.下面将介绍DNS分别在什么情况下使用这两种协议. TCP与UDP简介 TCP ...