正题

题目链接:https://www.luogu.com.cn/problem/P6775


题目大意

nnn种原材料,第iii个有did_idi​个,mmm道菜品都需要kkk个原料而且每道菜最多只能用两种材料。

要求构造方案使得满足条件。

1≤n≤500,n−2≤m≤5000,1≤k≤5000,(∑i=1ndi)=m×k1\leq n\leq 500,n-2\leq m\leq 5000,1\leq k\leq 5000,(\sum_{i=1}^nd_i)=m\times k1≤n≤500,n−2≤m≤5000,1≤k≤5000,(∑i=1n​di​)=m×k


解题思路

额去年线上赛的时候一点想法都没有是时候轮到我来一雪前耻历(虽然这题还是很难

首先我们注意到一个特殊的条件n−2≤mn-2\leq mn−2≤m,看上去没什么想法但是看一下数据范围有n−1=mn-1=mn−1=m和n−1≤mn-1\leq mn−1≤m两个部分分。

先考虑n−1=mn-1=mn−1=m的,就是原料比菜品多一个,那么我们一定有dmin<kd_{min}<kdmin​<k而且dmin+dmax>k(n≠2)d_{min}+d_{max}>k(n\neq 2)dmin​+dmax​>k(n​=2)。

嗯所以我们每次拿最少的一个原料和最多的一个原料做一个菜那么依旧满足n−1=mn-1=mn−1=m的条件。

然后考虑n≤mn\leq mn≤m的情况,不难发现肯定有dmax≥kd_{max}\geq kdmax​≥k,所以我们直接拿最多的来做一道菜那么要不n−1,m−1n-1,m-1n−1,m−1要么m−1m-1m−1变成n−1=mn-1=mn−1=m的情况。

之后是n−2=mn-2=mn−2=m的做法,这个是本题的核心难点。

在洛谷题解上看到过一个有趣的证明,我们可以把原料看成一个点,菜品所用的两个原料看成一条边,那么因为m=n−2m=n-2m=n−2所以这张图一定是不连通的,那么至少会被分成两棵树。

发现对于树就是m=n−1m=n-1m=n−1的情况,所以其实是相当于我们要把m=n−2m=n-2m=n−2的情况分成两个m=n−1m=n-1m=n−1的情况。

而且因为m=n−1m=n-1m=n−1一定有解所以我们只需要考虑怎么分就好了。

相当于我们要找出一个原料集合SSS使得
∑i∈Sdi=(∣S∣−1)k⇒∑i∈S(di−k)=−k\sum_{i\in S}d_i=(|S|-1)k\Rightarrow \sum_{i\in S}(d_i-k)=-ki∈S∑​di​=(∣S∣−1)k⇒i∈S∑​(di​−k)=−k

然后直接dpdpdp的复杂度是O(Tn2k)O(Tn^2k)O(Tn2k)的,加个bitsetbitsetbitset优化就是O(Tn2kw)O(T\frac{n^2k}{w})O(Twn2k​),可以通过本题


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<bitset>
using namespace std;
const int N=510,S=5e6+10,W=2500000;
struct node{int w,id;
}d[N];
struct cnode{int a,A,b,B;
}v[N*10];
int T,n,m,k,tot;
bool vis[N];
bitset<S>f[N];
vector<node> u;
bool cmp(node x,node y)
{return x.w<y.w;}
void Add(int a,int A,int b=0,int B=0)
{v[++tot]=(cnode){a,A,b,B};return;}
void solve(int m,vector<node> &d){int n=d.size();tot=0;while(m&&m>=n){sort(d.begin(),d.end(),cmp);Add(d[n-1].id,k);d[n-1].w-=k;m--;if(!d[n-1].w)d.pop_back(),n--;}if(m==n-1){while(m){sort(d.begin(),d.end(),cmp);swap(d[0],d[n-1]);Add(d[n-1].id,d[n-1].w,d[0].id,k-d[n-1].w);d[0].w-=k-d[n-1].w;d.pop_back();n--;m--;if(!d[0].w)swap(d[0],d[n-1]),d.pop_back(),n--;}}for(int i=1;i<=tot;i++){if(v[i].b)printf("%d %d %d %d\n",v[i].a,v[i].A,v[i].b,v[i].B);else printf("%d %d\n",v[i].a,v[i].A);}u.clear();return;
}
int main()
{scanf("%d",&T);f[0][W]=1;while(T--){scanf("%d%d%d",&n,&m,&k);for(int i=1;i<=n;i++)scanf("%d",&d[i].w),d[i].id=i;if(m==n-2){for(int i=1;i<=n;i++){int tmp=d[i].w-k;if(tmp>=0){f[i]=f[i-1];f[i]|=(f[i-1]<<tmp);}else{f[i]=f[i-1];f[i]|=(f[i-1]>>(-tmp));}}if(!f[n][W-k])puts("-1");else{memset(vis,0,sizeof(vis));for(int i=n,z=W-k;i>=1;i--){int tmp=d[i].w-k;if(f[i-1][z-tmp])u.push_back(d[i]),vis[i]=1,z-=tmp;}solve(u.size()-1,u);for(int i=1;i<=n;i++)if(!vis[i])u.push_back(d[i]);solve(u.size()-1,u);}}else{for(int i=1;i<=n;i++)u.push_back(d[i]);solve(m,u);}}return 0;
}

P6775-[NOI2020]制作菜品【贪心,dp】相关推荐

  1. URAL 1203 Scientific Conference(贪心 || DP)

    Scientific Conference 之前一直在刷计算几何,邀请赛连计算几何的毛都买见着,暑假这一段时间就做多校,补多校的题目,刷一下一直薄弱的DP.多校如果有计算几何一定要干掉-.- 题意:给 ...

  2. Codeforces Round #699 (Div. 2) E.Sorting Books(贪心+DP / 线段树)超高质量题解,看不懂来打我 ~

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 E - Sorting Books 一排书架上有 nnn 本书排成一排,每本书上有一个颜色 aia_i ...

  3. 【bzoj3174】[Tjoi2013]拯救小矮人 贪心+dp

    题目描述 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀上,知道最顶端的小矮人伸直胳膊可以碰到陷阱口.对于每一个小矮人,我们知道他从脚 ...

  4. HDU 4001 To Miss Our Children Time(2011年大连网络赛 A 贪心+dp)

    开始还觉得是贪心呢...  给你三类积木叫你叠楼房,给你的每个积木包括四个值:长 宽(可以互换) 高 类型d  d=0:你只能把它放在地上或者放在 长 宽 小于等于 自己的积木上面  d=1:你只能把 ...

  5. 【BZOJ4069】【APIO2015】巴厘岛的雕塑 [贪心][DP]

    巴厘岛的雕塑 Time Limit: 10 Sec  Memory Limit: 64 MB [Submit][Status][Discuss] Description 印尼巴厘岛的公路上有许多的雕塑 ...

  6. 杭电oj1257最少拦截系统—贪心/dp最大递增子序列

    附上题目链接:杭电oj1257 这个题目有动态规划和贪心两种解决方式. 贪心法1: 对于导弹我们知道只可以从大到小的反导,一个系统必须从大到小排列.那么我们就可以选择从最高的那个导弹入手,往右找仅次于 ...

  7. CF1155D Beautiful Array 贪心,dp

    CF115DBeautiful Array 题目大意:给一个有n个元素的a数组,可以选择其中一个区间的所有数都乘上x,也可以不选,求最大子序列和. 如果没有前面的操作,就是只求最大子序列和,我们都知道 ...

  8. CodeForces - 1481E Sorting Books(贪心+dp)

    题目链接:点击查看 题目大意:给出一个长度为 nnn 的序列,每次操作可以将任意一本书放到序列的末尾,问最少需要操作多少次,才能使得相同的数字挨在一起 题目分析:不难看出,对每个位置的数都操作一次,是 ...

  9. 2020ICPC(小米邀请赛2) - Knapsack(贪心+dp)

    题目链接:点击查看 题目大意:给出 n 个物品,每个物品都有体积和价值,现在问容量为 m 的背包最多可以装下多少价值的物品 题目分析:本题正解应该是斜率优化dp,然鹅看了大佬们的博客讲解后,感觉不是自 ...

最新文章

  1. VIM配置攻略(最强干货加强版)
  2. 空缺的2018-3-11《祖宗十九代》《缝纫机乐队》
  3. docker always_介绍两款Docker可视化工具
  4. 厉害了!Python+matplotlib制作8个排序算法的动画
  5. excel中的vlookup函数
  6. python3-day4(装饰器)
  7. 机器学习从入门到精通50讲(九)-基于 ANTLR 自己实现一个 SQL 解析器
  8. Ivanti罗琦:IT服务管理中“拧紧螺丝”要有门道儿!
  9. @PostConstruct注解详解
  10. 1.7 什么时候该改变开发_测试集和指标
  11. docker 安装依赖_史上最全Docker环境安装指南-让安装docker简单到爆
  12. 树状数组---Squared Permutation
  13. 【ArcGIS操作】3 数据制图篇
  14. 09月28日 pytorch与resnet(五) 转移学习
  15. 从Java看数据结构之——树和他的操作集
  16. 捕鱼达人python游戏项目,少儿编程体验课程项目,源码免费分享,内置详细注释,可更改游戏参数;关注获取更多资源
  17. 谷歌小恐龙PHP代码,Chrome小恐龙前端修改代码代码总结
  18. 使用 Layui 模板引擎在页面中插入 JS
  19. Codeforces 417D.Cunning Gena (状压DP)
  20. Criterion和Criteria

热门文章

  1. c语言出勤成绩,C语言课程设计学生考勤系统文档推荐 (10页)-原创力文档
  2. string 字符串中字符无效_JavaScript中的字符串(string)到底是什么?
  3. fanuc机器人控制柜接线_FANUC涂胶标定参考
  4. jquery 样式获取设置值_[JQuery] jQuery选择器ID、CLASS、标签获取对象值、属性、设置css样式...
  5. c语言 overflow_C语言和其他语言的不得不说的差别!
  6. laravel缓存html,Laravel 静态页面缓存 JosephSilber/page-cache - 码农天地
  7. java中立方根方法_java基础:4、java中Math类的常用方法?
  8. php用ajaxs上传图片_jquery+ajax+php 图片上传
  9. leetcode279. 完全平方数
  10. rust火箭基地主楼开启方法_Rust 为什么能成为 Stack Overflow 最受欢迎的语言?