meet in the middle 复习笔记
前言
若干年前看过现在又忘了。这么简单都忘
所以今天来重新复习一下。
正题
考虑这样的问题:
给定 \(n\) 个物品的价格,你有 \(m\) 块钱,每件物品限买一次,求买东西的方案数。
\(n\leq 40\),\(m\leq 10^{18}\)。
在看到数据范围之前,所有人的想法都是直接背包,看到数据范围后就寄了。
看样子不可用背包,那就用搜索吧。
直观的,我们考虑 \(O(2^n\times n)\) 的做法。
用 \(O(2^n)\) 的复杂度枚举每个物品是否购买,再 \(O(n)\) 复杂度判断是否合法。
但是看懂 \(n \leq 40\) 时就又寄了。
这是我们考虑 meet in the middle ,把时间复杂度变成 \(O(2^{\frac{n}{2}}+合并复杂度)\) 。
我们直接把当前的物品分成 \(1\sim \frac{n}{2}\) 和 \(\frac{n}{2}+1 \sim n\) 两个部分。
对于每一个部分我们都进行搜索,并把当前方案的花费 分两个数组 记录下来。
不难发现,到这为止,时间复杂度是 \(O(n^{\frac{n}{2}})\) 带有 \(2\) 的常数。
考虑怎么处理计算出来的各种方案的花费。
先考虑其中一个数组中的一种花费必选,然后直接二分查找即可。
(当然,之前要对这两个数组进行排序)
Code
笔者远古代码,没有人肉格式化,不喜勿喷。
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define ll long long
#define re register
#define N 50
#define M 2000005
int max(ll a,ll b){return a>b?a:b;}
int min(ll a,ll b){return a<b?a:b;}
int n,num,visit[N];
ll m,a[N],num1[M],num2[M];
ll b[N],c[N],ans=0;
inline ll read(){
ll s=0,t=1;
char c=getchar();
while((c<'0'||c>'9')&&c!='-')c=getchar();
if(c=='-')c=getchar(),t=-1;
while(c>='0'&&c<='9')s=(s<<1)+(s<<3)+(c^48),c=getchar();
return s*t;
}
void dfs_b(int k){
if(k>b[0]){
ll s=0;
for(int i=1;i<=b[0];i++)
if(visit[i]==1)s+=b[i];
num1[++num1[0]]=s;
return;
}
visit[k]=1;
dfs_b(k+1);
visit[k]=0;
dfs_b(k+1);
}
void dfs_c(int k){
if(k>c[0]){
ll s=0;
for(int i=1;i<=c[0];i++)
if(visit[i]==1)s+=c[i];
num2[++num2[0]]=s;
return;
}
visit[k]=1;
dfs_c(k+1);
visit[k]=0;
dfs_c(k+1);
}
ll find(ll need){
ll l=1,r=num2[0];
ll mid,maxn=0;
while(l<=r){
mid=(l+r)/2;
if(num2[mid]<=need){
maxn=max(maxn,mid);
l=mid+1;
}
else r=mid-1;
}
return maxn;
}
int main(void){
scanf("%d",&n);
m=read();
for(int i=1;i<=n;i++)
a[i]=read();
num=n/2;
for(int i=1;i<=num;i++)
b[++b[0]]=a[i];
for(int i=num+1;i<=n;i++)
c[++c[0]]=a[i];
memset(visit,0,sizeof(visit));
dfs_b(1);
memset(visit,0,sizeof(visit));
dfs_c(1);
sort(num2+1,num2+1+num2[0]);
for(int i=1;i<=num1[0];i++){
ll now=m-num1[i];
if(now<0ll)continue;
ans+=find(now);
}
printf("%lld\n",ans);
}
meet in the middle 复习笔记的更多相关文章
- Meet in the middle学习笔记
Meet in the middle(MITM) Tags:搜索 作业部落 评论地址 PPT中会讲的很详细 当搜索的各项互不影响(如共\(n\)个物品前\(n/2\)个物品选不选和后\(n/2\)个物 ...
- Java基础复习笔记系列 九 网络编程
Java基础复习笔记系列之 网络编程 学习资料参考: 1.http://www.icoolxue.com/ 2. 1.网络编程的基础概念. TCP/IP协议:Socket编程:IP地址. 中国和美国之 ...
- Java基础复习笔记系列 八 多线程编程
Java基础复习笔记系列之 多线程编程 参考地址: http://blog.csdn.net/xuweilinjijis/article/details/8878649 今天的故事,让我们从上面这个图 ...
- Java基础复习笔记系列 七 IO操作
Java基础复习笔记系列之 IO操作 我们说的出入,都是站在程序的角度来说的.FileInputStream是读入数据.?????? 1.流是什么东西? 这章的理解的关键是:形象思维.一个管道插入了一 ...
- Java基础复习笔记系列 五 常用类
Java基础复习笔记系列之 常用类 1.String类介绍. 首先看类所属的包:java.lang.String类. 再看它的构造方法: 2. String s1 = “hello”: String ...
- Java基础复习笔记系列 四 数组
Java基础复习笔记系列之 数组 1.数组初步介绍? Java中的数组是引用类型,不可以直接分配在栈上.不同于C(在Java中,除了基础数据类型外,所有的类型都是引用类型.) Java中的数组在申明时 ...
- Java基础复习笔记基本排序算法
Java基础复习笔记基本排序算法 1. 排序 排序是一个历来都是很多算法家热衷的领域,到现在还有很多数学家兼计算机专家还在研究.而排序是计算机程序开发中常用的一种操作.为何需要排序呢.我们在所有的系统 ...
- Meet in the middle
搜索是\(OI\)中一个十分基础也十分重要的部分,近年来搜索题目越来越少,逐渐淡出人们的视野.但一些对搜索的优化,例如\(A\)*,迭代加深依旧会不时出现.本文讨论另一种搜索--折半搜索\((meet ...
- SPOJ4580 ABCDEF(meet in the middle)
题意 题目链接 Sol 发现abcdef是互不相关的 那么meet in the middle一下.先算出abc的,再算def的 注意d = 0的时候不合法(害我wa了两发..) #include&l ...
随机推荐
- WPF样式和触发器
理解样式 样式可以定义通用的格式化特征集合. Style 类的属性 Setters.Triggers.Resources.BasedOn.TargetType <Style x:Key=&quo ...
- [AcWing 823] 排列
点击查看代码 #include<iostream> using namespace std; const int N = 10; int n; void dfs(int u, int nu ...
- centos 7.0 下安装FFmpeg软件 过程
这几天由于需要编写一个语音识别功能,用到了百度语音识别接口,从web端或小程序端传上来的音频文件是aac或者mp3或者wav格式的,需要使用FFmpeg进行格式转换,以符合百度api的要求. 安装FF ...
- python爬取豆瓣电影Top250(附完整源代码)
初学爬虫,学习一下三方库的使用以及简单静态网页的分析.就跟着视频写了一个爬取豆瓣Top250排行榜的爬虫. 网页分析 我个人感觉写爬虫最重要的就是分析网页,找到网页的规律,找到自己需要内容所在的地方, ...
- python模块,邮件推送交换机error级别以上log,django前端展示
前情概要 原syslog服务器只收集不推送日志,可以实时展示,服务器在海外内网,办公网做的有分流,到日志服务器的流量送到香港,其余流量国内,疫情期间在家办公,每次连接需要拨海外l2tp,挂着梯子访问国 ...
- 【动态UAC权限】无盾程序(win32&cmd)
可以看到两种不同的提权方式,注意是动态,用代码提权,而不是用清单文件提前处理. 函数都写好了,这里不多做解释. win32程序: 首先需要这俩头文件,第二个我忘了啥函数要用了,总之出问题加上就对了:( ...
- [THUSCH2017] 杜老师
description \(T\)次询问,每次问\(L,L+1...R\)有多少种子集满足子集中乘积为完全平方数. solution 50pt 首先双倍经验 通常的思路是:平方数即每个质因子指数为偶 ...
- USACO 刷题小记
\(\text{High Card Low Card}\) USACO2015DEC Platinum T2 贝西和艾尔西在玩游戏.有 \(2n\) 张牌,牌上的数字是 \(1\) 到 \(2n\) ...
- 联发科 (MTK) sensor bring up
MT6768平台 1.添加驱动文件 2.添加硬件配置支持 3.添加硬件配置 4.添加编译配置 5.分配空间(非必要,当代码量超过当前空间大小时将会报错,根据报错log改大小即可.) 6.兼容配置 7. ...
- POJ1821 Fence 题解报告
传送门 1 题目描述 A team of $k (1 <= K <= 100) $workers should paint a fence which contains \(N (1 &l ...