洛谷 P6775 - [NOI2020] 制作菜品(找性质+bitset 优化 dp)
好久没写过题解了,感觉几天没写手都生疏了
首先这种题目直接做肯定是有些困难的,不过注意到题目中有个奇奇怪怪的条件叫 \(m\ge n-2\),我们不妨从此入手解决这道题。
我们先来探究 \(m=n-1\) 的情况,观察大样例可知这种情况一定有解,我们不妨考虑这样一个贪心:假设 \(x\) 为使 \(d_i\) 取到最小值的 \(i\),\(y\) 为使得 \(d_i\) 取到最大值的 \(i\),那么我们就用 \(d_x\) 个原料 \(x\) 与 \(k-d_x\) 个原料 \(y\) 制作成一个菜品,这样会消耗掉一种菜品(\(x\)),重复 \(n-1\) 轮即可。
为什么这样贪心是对的?我们考虑一次操作,为了证明这次操作是合法的,我们需证明以下两个结论:
- \(d_x<k\)
- \(k-d_x\le d_y\),即 \(d_x+d_y\ge k\)。
这两个结论都可采用反证法证明。关于结论一,假设命题不成立,那么 \(d_x\ge k\),而由 \(d_x\) 的定义知 \(d_i\ge d_x\ge k\),故 \(\sum\limits_{i=1}^nd_i\ge nd_x\ge nk>mk\),矛盾。关于结论二,假设命题不成立,那么 \(d_y<k-d_x\),由 \(d_y\) 的定义知 \(d_i\le d_y<k-d_x\),故 \(\sum\limits_{i=1}^nd_i<(n-1)(k-d_x)+d_x=k+(n-2)(k-d_x)<k+(n-2)k=(n-1)k\),矛盾!
因此每次操作都是合法的。而显然每次操作之后都会有一个原料被消耗尽,因此我们就由 \(n\) 的情况过渡到了 \(n-1\) 的情况。又当 \(n=2\) 时有 \(d_1+d_2=k\),可以直接把两种原料搞在一起,符合条件。由数学归纳法可知这个贪心是没问题的。
接下来再考虑 \(m\ge n\) 的情况,我们考虑将 \(m\ge n\) 的情况向 \(m=n-1\) 的情况过渡,还是设 \(x\) 为使 \(d_i\) 取到最小值的 \(i\),\(y\) 为使得 \(d_i\) 取到最大值的 \(i\),这里有一个显然的结论,那就是 \(d_y\ge k\),否则 \(\sum\limits_{i=1}^nd_i<nk\le mk\),矛盾。因此我们只需每次选取 \(d_i\) 最大的 \(i\) 并消耗掉 \(k\) 克 \(i\) 原料,直到 \(m=n-1\) 为止即可。
最后考虑 \(m=n-2\) 的情况,再次观察样例可知这种情况就不一定有解了,那 \(m=n-2\) 的情况究竟什么时候有解,什么时候无解呢?
又到了考验选手观察能力的时候了,这里还有第四个结论,那就是 \(m=n-2\) 的情况有解当且仅当存在 \(S\subset\{1,2,3,\cdots,n\}\) 满足 \(\sum\limits_{x\in S}d_x=k(|S|-1)\)。
证明:充分性显然,记全集为 \(U=\{1,2,3,\cdots,n\}\),既然 \(S\) 满足 \(\sum\limits_{x\in S}d_x=k(|S|-1)\),那么 \(T=U-S\) 也一定满足 \(\sum\limits_{x\in T}d_x=k(|T|-1)\),因此我们只需对 \(S,T\) 分别执行 \(m=n-1\) 的操作即可。必要性:我们假设对于某个序列 \(d_1,d_2,\cdots,d_n\) 存在符合要求的解,我们考虑对于两个原料 \(i,j\),如果它们曾共同作为原料出现在这 \(n-2\) 个菜品中的某一个中,那么就连一条边 \((i,j)\),特别地如果一种原料单独做成一道菜品就连一条自环。显然这样会得到一张图 \(G=(V,E)\),并且 \(|V|=n,|E|\le n-2\),因此 \(G\) 不连通,而显然 \(G\) 中一定存在一个连通块是一棵树(否则假设所有联通块都存在环,那么边数必然 \(\ge n\))我们假设构成这个连通块的点集为 \(S\),这就是我们要找的集合 \(S\)。因此如果存在合法的方案,就必定存在符合要求的集合 \(S\)。
那么怎样找出这样的集合 \(S\) 呢?考虑对 \(\sum\limits_{x\in S}d_x=k(|S|-1)\) 进行变形,两边同时减去 \(k|S|\) 可得 \(-k|S|+\sum\limits_{x\in S}d_x=-k\),再将 \(-k\) 分配到求和号中可得 \(\sum\limits_{x\in S}d_x-k=-k\),这个长得一脸 01 背包的样子。我们考虑 \(dp_{i,j}\) 为当前考虑到前 \(i\) 个数,是否存在一个集合 \(S\) 使得 \(\sum_{x\in S}d_x-k=j\),按照就的 01 背包的套路即可,这样复杂度是 \(n^2k\) 的,可以拿到 \(85\) 分。不过发现 \(dp\) 数组每一个值的取值都只有 01 两种可能,故考虑 bitset
优化 \(dp\),具体来说我们对开一个 bitset<MAXN*MAXK*2+5> dp[MAXN+5]
,其中第 \(i\) 个 bitset
的第 \(j\) 位为 \(1\) 表示 \(dp_{i,j}=1\),否则表示 \(dp_{i,j}=0\)。对于形如 \(dp_{i,j}|=dp_{i-1,j-x}\) 的转移方程,我们就令 \(dp_i|=dp_{i-1}<<x\),显然二者是等价的,复杂度也就降到了 \(\dfrac{n^2k}{\omega}\)。
求完 bitset
之后检验 \(dp_{n,-k}\) 是否等于 \(1\),如果 \(dp_{n,-k}=0\) 则无解,否则按照输出路径的套路找出符合要求的集合 \(S\),然后用 \(m=n-1\) 的算法输出方案即可。
u1s1 bitset yyds!
const int MAXN=500;
const int MAXK=5e3;
int n,m,k,a[MAXN+5];
void work(vector<pii> vx,int n,int m){
set<pii> st;
for(int i=0;i<vx.size();i++) st.insert(vx[i]);
for(int i=1;i<=m;i++){
if(m>=n){
pii pp=*st.rbegin();st.erase(st.find(pp));
printf("%d %d\n",pp.se,k);--m;st.insert(mp(pp.fi-k,pp.se));
} else {
pii p1=*st.begin();st.erase(st.find(p1));
pii pn=*st.rbegin();st.erase(st.find(pn));
printf("%d %d %d %d\n",p1.se,p1.fi,pn.se,k-p1.fi);
st.insert(mp(pn.fi-(k-p1.fi),pn.se));
}
}
}
bitset<MAXN*MAXK*2+5> dp[MAXN+5];
void clear(){
for(int i=0;i<=n;i++) dp[i].reset();
}
vector<pii> v1,v2;
void findpath(int x,int v){
if(!x) return;
if(dp[x-1][v]){
v1.pb(mp(a[x],x));
findpath(x-1,v);
} else {
v2.pb(mp(a[x],x));
findpath(x-1,v-(a[x]-k));
}
}
void solve(){//remember to make it first
scanf("%d%d%d",&n,&m,&k);clear();
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
if(m>=n-1){
vector<pii> v;
for(int i=1;i<=n;i++) v.pb(mp(a[i],i));
work(v,n,m);return;
} int delta=n*k;dp[0][delta]=1;
for(int i=1;i<=n;i++){
int t=a[i]-k;
if(t>=0) dp[i]=dp[i-1]|(dp[i-1]<<t);
else dp[i]=dp[i-1]|(dp[i-1]>>(-t));
}
if(!dp[n][delta-k]){puts("-1");return;}
v1.clear();v2.clear();findpath(n,delta-k);
// for(int i=0;i<v1.size();i++) printf("%d ",v1[i].se);printf("\n");
// for(int i=0;i<v2.size();i++) printf("%d ",v2[i].se);printf("\n");
work(v1,v1.size(),v1.size()-1);
work(v2,v2.size(),v2.size()-1);
}
int main(){
int qu;scanf("%d",&qu);
for(int i=1;i<=qu;i++) solve();
return 0;
}
洛谷 P6775 - [NOI2020] 制作菜品(找性质+bitset 优化 dp)的更多相关文章
- 洛谷P2216: [HAOI2007]理想的正方形 单调队列优化DP
洛谷P2216 )逼着自己写DP 题意: 给定一个带有数字的矩阵,找出一个大小为n*n的矩阵,这个矩阵中最大值减最小值最小. 思路: 先处理出每一行每个格子到前面n个格子中的最大值和最小值.然后对每一 ...
- BZOJ1563/洛谷P1912 诗人小G 【四边形不等式优化dp】
题目链接 洛谷P1912[原题,需输出方案] BZOJ1563[无SPJ,只需输出结果] 题解 四边形不等式 什么是四边形不等式? 一个定义域在整数上的函数\(val(i,j)\),满足对\(\for ...
- 【洛谷3648】[APIO2014] 序列分割(斜率优化DP)
点此看题面 大致题意: 你可以对一个序列进行\(k\)次分割,每次得分为两个块元素和的乘积,求总得分的最大值. 区间\(DPor\)斜率优化\(DP\) 这题目第一眼看上去感觉很明显是区间\(DP\) ...
- 洛谷P2569 (BZOJ1855)[SCOI2010]股票交易 【单调队列优化DP】
Description 最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,lxhgww预测到了未来T天内某只股票的走势,第i天的股票买入价 ...
- 洛谷 P2254 [NOI2005]瑰丽华尔兹(单调栈优化DP)
题目描述 不妨认为舞厅是一个N行M列的矩阵,矩阵中的某些方格上堆放了一些家具,其他的则是空地.钢琴可以在空地上滑动,但不能撞上家具或滑出舞厅,否则会损坏钢琴和家具,引来难缠的船长.每个时刻,钢琴都会随 ...
- 洛谷2900 [USACO08MAR]土地征用Land Acquisition (斜率优化+dp)
自闭的一批....为什么斜率优化能这么自闭. 首先看到这个题的第一想法一定是按照一个维度进行排序. 那我们不妨直接按照\(h_i\)排序. 我们令\(dp[i]\)表示到了第\(i\)个矩形的答案是多 ...
- 洛谷3195 [HNOI2008]玩具装箱TOY(斜率优化+dp)
qwq斜率优化好题 第一步还是考虑最朴素的\(dp\) \[dp=dp[j]+(i-j-1+sum[i]-sum[j])^2 \] 设\(f[i]=sum[i]+i\) 那么考虑将上述柿子变成$$dp ...
- 洛谷 P6776 - [NOI2020] 超现实树(找性质,神仙题)
洛谷题面传送门 nb tea 一道! 首先考虑怎样入手分析这个看似非常不可做的问题.首先题目涉及高度无穷的树,根本枚举不了.不过我们冷静一下就会发现,如果我们记 \(mx=\max\limits_{i ...
- 【洛谷 5002】专心OI - 找祖先 (树上计数)
专心OI - 找祖先 题目背景 \(Imakf\)是一个小蒟蒻,他最近刚学了\(LCA\),他在手机\(APP\)里看到一个游戏也叫做\(LCA\)就下载了下来. 题目描述 这个游戏会给出你一棵树,这 ...
随机推荐
- 华为在HDC2021发布全新HMS Core 6 宣布跨OS能力开放
[2021年10月22日·东莞]华为开发者大会 2021(Together)于今天正式开幕,华为在主题演讲中正式发布全新的HMS Core 6,向全球开发者开放7大领域的69个Kit和21,738个A ...
- 【数据结构 C++】排序——冒泡、插入、选择、希尔、归并、快排、堆排序
LeetCode 912. 排序数组 给你一个整数数组 nums,请你将该数组升序排列. 示例 1: 输入:nums = [5,2,3,1] 输出:[1,2,3,5] 示例 2: 输入:nums = ...
- 【c++ Prime 学习笔记】第17章 标准库特殊设施
17.1 tuple类型 tuple是类似pair的模板: pair和tuple的成员类型都可以不相同 pair恰好有两个成员,tuple可有任意数量的成员 按照不同参数数量和类型实例化出的tuple ...
- [技术博客] BeautifulSoup4分析网页
[技术博客] BeautifulSoup4分析网页 使用BeautifulSoup4进行网页文本分析 前言 进行网络爬虫时我们需要从网页源代码中提取自己所需要的信息,分析整理后存入数据库中. 在pyt ...
- OO面向对象第三次作业总结
面向对象第三次作业总结 一.JML基础梳理及工具链 注释结构 行注释://@annotation 块注释:/*@ annotation @*/ 两种注释都是放在被注释部分上面. 常见表达式 原子表达式 ...
- OO_JAVA_表达式求导_单元总结
OO_JAVA_表达式求导_单元总结 这里引用个链接,是我写的另一份博客,讲的是设计层面的问题,下面主要是对自己代码的单元总结. 程序分析 (1)基于度量来分析自己的程序结构 第一次作业 程序结构大致 ...
- OO--第三单元规格化设计 博客作业
OO--第三单元规格化设计 博客作业 前言 第三单元,我们以JML为基础,先后完成了 PathContainer -> Graph -> RailwaySystem 这是一个递进的过程,代 ...
- js模板引擎laytpl的使用
在我们实际的开发过程中,可能会遇到使用ajax去后台获取一堆的数据,然后动态的渲染到页面上.比如:去后台获取一个list集合,然后将数据以表格的形式展示在页面上.另外一种可能发生的情况就是页面上需要批 ...
- Pogo-Cow S
这题出在单调队列优化dp里,就离谱好吧...... 对不住了上来先喷一波,不过离谱是确实的 dp的含义也很简单,就是说从j到i的分数最大值 直接上代马,里面说的很详细了 1 #include<b ...
- 汇编--LDR
转载:https://my.oschina.net/zengsai/blog/23733 ARM LDR 伪指令的格式: LDR Rn, =expr 如果name是立即数的话LDR R0,=0X123 ...