当$n-1\le m$,不妨令$d_{1}\le d_{2}\le...\le d_{n}$,则$(n-1)k\le mk=\sum_{i=1}^{n}d_{i}\le d_{1}+(n-1)d_{n}$
将这个拆成两部分,即$(n-2)k+k$和$(n-2)d_{n}+(d_{1}+d_{n})$,由于后者大于等于前者,所以两项中必然有一项大于等于前者,容易发现一定存在$k\le d_{1}+d_{n}$
那么就可以不断贪心将$d_{1}$和$d_{n}$匹配,每一次必然会至少消除一个数,而最后一次因为总和恰好为$mk$所以必然全部消除
当$m=n-2$,此时合法当且仅当存在一个集合$S\subset \{1,2,...,n\}$使得$\sum_{i\in S}d_{i}=(|S|-1)k$
证明:充分性,如果存在,将两部分分开处理,即有解且已构造得出
必要性,可以证明若存在合法解,必然存在一组使得每次操作使至少一个点变为$0$(显然消除掉一定更优)
构造:将每一个点向消除掉自己的点连无向边,显然这张图不存在大于2的环(考虑环上操作的先后顺序即可)
因此即去除掉重边后,这张图是一棵森林且有至少2棵树(否则有$n-1$次操作),其中任意一棵子树即可作为集合$S$
考虑怎么求出这个集合$S$,暴力$dp$令$f[i][j][k]$表示前$i$个点中选$j$个点和能否为$k$,复杂度为$o(n^{3}k)$无法通过
如何使得其与$|S|$无关,即$S$需满足$\sum_{i\in S}d_{i}-k=-k$,同时权值范围仅变为$[-nk,nk]$,因此复杂度降为$o(n^{2}k)$
问题即一个01背包的存在性判断,可以用$bitset$来优化,复杂度降为$o(\frac{n^{2}k}{32})$,可以通过

 1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 505
4 set<pair<int,int> >s;
5 int t,n,m,k,d[N],vis[N];
6 bitset<N*N*20>f[N];
7 void work(int m){
8 for(int i=1;i<=m;i++){
9 int x=(*s.begin()).second;
10 s.erase(s.begin());
11 if (d[x]>=k){
12 printf("%d %d",x,k);
13 d[x]-=k;
14 if (d[x])s.insert(make_pair(d[x],x));
15 }
16 else{
17 int y=(*(--s.end())).second;
18 s.erase(--s.end());
19 printf("%d %d %d %d",x,d[x],y,k-d[x]);
20 d[y]-=k-d[x];
21 if (d[y])s.insert(make_pair(d[y],y));
22 d[x]=0;
23 }
24 if (i!=m)printf("\n");
25 }
26 }
27 int main(){
28 freopen("dish.in","r",stdin);
29 freopen("dish.out","w",stdout);
30 scanf("%d",&t);
31 bool flag=0;
32 while (t--){
33 if (flag)printf("\n");
34 flag=1;
35 scanf("%d%d%d",&n,&m,&k);
36 for(int i=1;i<=n;i++)scanf("%d",&d[i]);
37 if (n-1<=m){
38 for(int i=1;i<=n;i++)s.insert(make_pair(d[i],i));
39 work(m);
40 continue;
41 }
42 memset(vis,0,sizeof(vis));
43 for(int i=0;i<=n;i++)f[i].reset();
44 f[0][n*k]=1;
45 bool flagg=0;
46 for(int i=1;i<=n;i++){
47 f[i]=f[i-1];
48 if (d[i]>=k)f[i]|=(f[i-1]<<d[i]-k);
49 else f[i]|=(f[i-1]>>k-d[i]);
50 if (f[i][(n-1)*k]){
51 flagg=1;
52 for(int j=i,t=(n-1)*k;j;j--)
53 if (f[j-1][t-(d[j]-k)]){
54 vis[j]=1;
55 t-=d[j]-k;
56 }
57 for(int j=1;j<=n;j++)
58 if (vis[j])s.insert(make_pair(d[j],j));
59 work(s.size()-1);
60 printf("\n");
61 for(int j=1;j<=n;j++)
62 if (!vis[j])s.insert(make_pair(d[j],j));
63 work(s.size()-1);
64 break;
65 }
66 }
67 if (!flagg)printf("-1");
68 }
69 return 0;
70 }

[loj3342]制作菜品的更多相关文章

  1. 洛谷 P6775 - [NOI2020] 制作菜品(找性质+bitset 优化 dp)

    题面传送门 好久没写过题解了,感觉几天没写手都生疏了 首先这种题目直接做肯定是有些困难的,不过注意到题目中有个奇奇怪怪的条件叫 \(m\ge n-2\),我们不妨从此入手解决这道题. 我们先来探究 \ ...

  2. P6775-[NOI2020]制作菜品【贪心,dp】

    正题 题目链接:https://www.luogu.com.cn/problem/P6775 题目大意 \(n\)种原材料,第\(i\)个有\(d_i\)个,\(m\)道菜品都需要\(k\)个原料而且 ...

  3. [NOI2020] 制作菜品

    看懂题目是生产第一要素. 考虑\(m = n - 1\)则必定有解.我们每次选择最小的和最大的拼在一起即可. 当\(m\)大于\(n\),那么我们只要每次选择最大的给他消掉即可. \(m = n - ...

  4. 用POLARDB构建客到智能餐饮系统实践

    在新零售成为大趋势的今天,餐饮行业也加入到这一浪潮之中.智能餐饮系统将帮助餐饮行业从多个维度提升自己的运营能力和收益,而打造智能餐饮系统SaaS化能力也成为了目前的一个热点.本文中果仁软件联合创始人& ...

  5. Activity 学习(二) 搭建第一个Activity流程框架

    本次示例使用的IDER测试完成 测试背景 : xx饿了去饭店吃饭  需要先和服务员点餐  点完餐后服务员将菜品传递给厨师制作  制作完成后吃饱 一 :创建流程图 创建上一篇测试成功出现的BpmnFil ...

  6. NOI2020网上同步赛 游记

    Day1 预计得分:\(32pts\)(我裂开了--) T1 美食家 表示考试的时候想到了关于矩阵快速幂的想法,甚至连分段后怎么处理都想好了,但是没有想到拆点,还有不知道怎么处理重边(这个考虑是多余的 ...

  7. NOI2020 同步赛划水记

    因为太菜了没去现场参加 NOI 就算去了估计也只能混个Fe(雾) "两天都会各有一道签到题,争取拿到70分.剩下的题每道题打30分暴力.每天130分,就能稳拿Ag了."--ls D ...

  8. [HNOI 2015]菜肴制作

    Description 知名美食家小 A被邀请至ATM 大酒店,为其品评菜肴. ATM 酒店为小 A 准备了 N 道菜肴,酒店按照为菜肴预估的质量从高到低给予 1到N的顺序编号,预估质量最高的菜肴编号 ...

  9. 【AR实验室】ARToolKit之制作自己的Marker/NFT

    0x00 - 前言 看过example后,就会想自己动动手,这里改改那里修修.我们先试着添加自己喜欢的marker/nft进行识别. 比如我做了一个法拉利的marker: 还有网上找了一个法拉利log ...

随机推荐

  1. DL4J实战之三:经典卷积实例(LeNet-5)

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  2. web_security学习路线

    一.了解黑客是如何工作的 1.在虚拟机配置Linux系统 2.漏洞测试工具 3.msf控制台 4.远程工具RATS 5.远程访问计算机 6.白帽 二.技术基础 漏斗扫描工具AWVS AWVS简介 安装 ...

  3. 题解 [APIO2013]道路费用

    link Description 幸福国度可以用 N 个城镇(用 1 到 N 编号)构成的集合来描述,这些城镇 最开始由 M 条双向道路(用 1 到 M 编号)连接.城镇 1 是中央城镇.保证一个 人 ...

  4. 洛谷3119 草鉴定(tarjan)

    题目大意 约翰有\(n\)块草场,编号\(1\)到\(n\),这些草场由若干条单行道相连.奶牛贝西是美味牧草的鉴赏家,她想到达尽可能多的草场去品尝牧草. 贝西总是从\(1\)号草场出发,最后回到\(1 ...

  5. qsort()函数的使用

    函数声明 void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*)) 参数 ...

  6. pta天梯训练赛补题

    7-1谁先倒 划拳是古老中国酒文化的一个有趣的组成部分.酒桌上两人划拳的方法为:每人口中喊出一个数字,同时用手比划出一个数字.如果谁比划出的数字正好等于两人喊出的数字之和,谁就输了,输家罚一杯酒.两人 ...

  7. iOS能否自动扫描周边wifi信息并通过密码连接

    能否获取系统wifi列表信息 不能,只能获取用户当前连接的wifi信息 https://developer.apple.com/forums/thread/112177 https://develop ...

  8. 【UE4 C++】Tick的三种方式、异步蓝图节点

    Tick的三种方式 包括 默认 Tick (Actor.Component.UMG) TimerManager 定时器 FTickableGameObject 可以写原生 Object 也可以继承UO ...

  9. LeetCode:堆专题

    堆专题 参考了力扣加加对与堆专题的讲解,刷了些 leetcode 题,在此做一些记录,不然没几天就忘光光了 力扣加加-堆专题(上) 力扣加加-堆专题(下) 总结 优先队列 // 1.java中有优先队 ...

  10. Sharding-JDBC自定义复合分片算法

    Sharding-JDBC自定义复合分片算法 一.背景 二.需求 1.对于客户端操作而言 2.对于运营端操作而言 三.分片算法 1.客户id和订单id的生成规则 2. 确定数据落在那个表中 3.举例说 ...