• 折半搜索-oier复健练习题目


    算法介绍:

    折半搜索常用于复杂度O(n!)级的搜索问题,当我们发现很显然可以将问题划分为两部分分别搜索枚举,再合二为一求出最终答案时,我们可以选择使用折半搜索。

    常见数据规模:

    对于答案的值域往往没有要求,只对给出元素个数 n n n 有一定要求:

    n ≤ 50 n\leq50 n50

    例题:

    来源:东BOJ:oj.neu.edu.cn

    在这里插入图片描述

    解题思路:

    设目标值x为 g o a l goal goal,最终种类数为 a n s ans ans

    如果纯暴力解决,算法复杂度 O ( 2 n ) O(2^n) O(2n),而 n n n最大可达到 40 40 40,显然是会超时的

    所以我选择先枚举出前半部分元素,即 t 1 ∼ t n / 2 {t_1} \sim {t_{n/2}} t1tn/2所能生成的所有值 t o t 1 tot_1 tot1所组成的集合 s s s

    再去搜索 t n / 2 + 1 ∼ t n {t_{n/2+1}} \sim {t_{n}} tn/2+1tn能组合产生的所有的值 t o t 2 tot_2 tot2,对于每次搜索产生的 t o t 2 tot_2 tot2,都去 s s s中二分搜索出 x − t o t 2 x-tot_2 xtot2的值,如果 x − t o t 2 x-tot_2 xtot2存在,就是找到可行方案了,It’s MYGO!, 就把 t y p e [ x − t o t 2 ] type[x-tot_2] type[xtot2]加到最终答案 a n s ans ans中。

    如果没有找到,就不是可行方案,乐队就要解散了(大悲)

    关于我曲折的debug过程

    最开始是 T L E TLE TLE,这很正常,毕竟 s s s规模还是挺大的,硬搜肯定会 T T T掉。
    显然优化就是 u n i q u e unique unique去重,然后统计 s s s每个元素的出现次数。
    结果还是过不了,一堆 W A WA WA
    心态就彻底炸了
    这题都做不出来是不是该速速remake了
    胃疼头疼的debuff就一起上了。
    最后发现,是 u n i q u e unique unique写错了…
    本来我定义的 s s s大小是 c n t cnt cnt,实际我给写成 n n n了…

    正确代码:
    在这里插入图片描述

    错误代码
    在这里插入图片描述

    无话可说。。。。总之最后是过了,还算不错

    完整代码

    #include
    using namespace std;
    const int maxn=2e6+60;
    long long si[maxn];
    int cnt,n;
    long long a[50],goal;
    long long tot1=0,tot2=0;
    long long minn;
    long long type[maxn];
    int len=0;
    void dfs1(int x)
    {
    	if(x==n/2+1)
    	{
    		si[++cnt]=tot1;
    		return;
    	}
    	tot1+=a[x];
    	if(tot1<=goal) dfs1(x+1);
    	tot1-=a[x];
    	dfs1(x+1); 
    }
    long long ans=0;
    int ans_id=0;
    bool jud(long long res)
    {
    	int l=1,r=len;
    	while(l<r)
    	{
    		int mid=(l+r+1)>>1;
    		if(si[mid]==res)
    		{
    			ans_id=mid;
    			return true;
    		}
    		if(si[mid]<=res) l=mid;
    		else r=mid-1;
    	}
    	return false;/*
    	for(int i=1;i<=cnt;++i) 
    	{
    		if(si[i]==res) ++ans;	
    	}
    	return false;*/
    }
    void dfs2(int x)
    {
    	if(x==n+1)
    	{
    		if(tot2==goal) ans+=type[1];
    		else if(jud(goal-tot2)) ans+=type[ans_id];
    		return;
    	}
    	tot2+=a[x];
    	if(tot2+minn<=goal) dfs2(x+1);
    	tot2-=a[x];
    	dfs2(x+1);
    }		
    int main()
    {
    	scanf("%d%lld",&n,&goal);
    	for(int i=1;i<=n;++i)  scanf("%lld",&a[i]);
    	dfs1(1);
    	minn=si[1];
    	for(int i=2;i<=cnt;++i) minn=min(minn,si[i]);
    	sort(si+1,si+cnt+1);
    	long long now=si[1];
    	long long cnt_now=1;
    	len=0;
    	for(int i=2;i<=cnt;++i)
    	{
    		if(si[i]==now) ++cnt_now;
    		else
    		{
    			type[++len]=cnt_now;
    			now=si[i];
    			cnt_now=1;	
    		}
    	}
    	type[++len]=cnt_now;
    	unique(si+1,si+cnt+1)-si-1;
    	dfs2(n/2+1);
    	printf("%lld\n",ans);
    //	printf("len=%d\n",len);
    //	for(int i=1;i<=len;++i) printf("%d ",type[i]);
    	return 0;	
    }
    /*
    4 2
    1 1 1 1
    */
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92

    题都看完了,就来推一首MYGO翻唱吧

    【歌ってみた】少女レイ(少女REI) covered by 燈

    一首不够?再来一个吧

    【歌ってみた】「二息歩行 (Reloaded)」covered by 燈

  • 相关阅读:
    排序算法一 直接插入排序,希尔排序,直接选择排序,堆排序和冒泡排序
    常用技能点:Java中数组复制的三种方式
    Facebook的预填问题默认可以设定哪些类型。
    2023-09-28 mysql-代号m-schema调研-文档记录
    Dubbo windows下Dubbo安装及相关配置
    java基于微信小程序的停车场自动收费管理系统 uniapp 小程序
    C# winfrom窗体最小化任务栏托盘
    httprunner3.x总结23 - 解决批量执行中重复登陆的问题
    Kubernetes(k8s) 架构原理一文详解
    R语言作图——Heatmap(热图)
  • 原文地址:https://blog.csdn.net/Mint_hexagram/article/details/133962811