• 2020.10.1 清北学堂 J2综合强化营 D1 搜索笔记


    搜索

    (1).分类

    • 解方案问题 例:(N)个数里选(M)个数,求使这M个数最大的一种方案
    • 解数量问题 例:(N)个数里选(M)个数,求使这M个数最大的方案数
    • 最优解问题 例:(N)个数里选(M)个数,求这M个数和的最大值

    (2).(BFS)(DFS) 的选择问题

    (BFS)选择条件:从一个状态转移到另一个状态所需代价是(1) & 最优解问题
    例:走迷宫,从一个格子走到另一个格子需要走一步,即代价为(1)

    若否,则用(DFS)

    (3).剪枝方法

    • 可行性剪枝
    • 最优解剪枝

    例:(DFS)(N)个数里选(M)个数,求这(M)个数和的最大值:

    inline void DFS(int p,int k,int sum){	//p当前选到第几个数,选了k个数,其和为sum
    	if(n-p<m-k) return;	//可行性剪枝,如果继续搜不可能出现合法的解时,直接结束
    	if(p>n){	//共n个数
    		if(k==m) ans=max(ans,sum);	//需选m个数
    		return 0;
    	}
    	dfs(p+1,k,sum);	//不选
    	if(k<m) dfs(p+1,k+1,sum+a[p]);	//能选的情况下选
    }
    

    在保证所有数大于(0)时,求最小值:

    inline void DFS(int p,int k,int sum){
    	if(sum>ans) return;	//最优解剪枝,当前的解已经比最优解好,直接结束
    	if(n-p<m-k) return;	
    	if(p>n){
    		if(k==m) ans=min(ans,sum);	
    		return 0;
    	}
    	dfs(p+1,k,sum);	
    	if(k<m) dfs(p+1,k+1,sum+a[p]);
    }
    

    (4).优化技巧

    (1).改变搜索顺序优化:(正着搜,倒着搜,随机打乱搜)

    inline void DFS(int p,int k,int sum){
    	if(sum>ans) return;	//最优解剪枝,当前的解已经比最优解好,直接结束
    	if(n-p<m-k) return;	
    	if(p>n){
    		if(k==m) ans=min(ans,sum);	
    		return 0;
    	}
    	if(k<m) dfs(p+1,k+1,sum+a[p]);	
    	//main函数里排序了,从小到大,改变搜索顺序,先选再不选,直接第一次搜索出最优解
    	//配合最优解剪枝,时间复杂度可以近乎达到O(nlogn)
    	dfs(p+1,k,sum);	
    }
    int main(){
    	int n;
    	cin>>n;
    	for(int i=1;i<=n;i++) cin>>a[i];
    	sort(a+1,a+n+1);	//排序配合最优解剪枝
    	DFS(1,0,0);	
    }
    

    (2).随机打乱:

    #include<algorithm>
    random_shuffle(a+1,a+n+1);
    

    (3).卡时优化:

    #include<ctime>
    #include<algorithm>
    inline void DFS(){
    	//dfs
    }
    int main(){
    	cout<<clock()<<endl;	
    	//clock()函数返回程序运行的时间。
    	//在Windows系统下,单位为毫秒(ms)
    }
    

    注:卡时时不要卡太紧,程序运行退出还会耗用一部分时间

    例:卡之前的DFS程序到(900ms),(假设限定时间为(1s))防止TLE

    思路:在当前测试点即将TLE时,直接输出答案

    TLE一定(0pts),但直接输出不一定(0pts)

    #include<ctime>
    #include<algorithm>
    inline void DFS(){
    	if(clock()>=900){
    		//输出答案
    		exit(0);	//直接退出程序
    	}
    }
    
  • 相关阅读:
    Alook搭配JS脚本完美食用
    分享小米刷机教程/线刷(工具支持小米华为一加)
    iPhone 无需越狱修改wx+zfb+qq步数
    如果SELECT语句中没有结果,则使用CASE返回字符串
    MSSQLServer 正在显示"正在还原...."
    C# 小技巧
    C#使用Select方法快速获取List集合集合中某个属性的所有值集合
    C#中使用Sum方法对List集合进行求和操作
    sql日期函数
    sql只根据某一字段去重,并保留其他字段
  • 原文地址:https://www.cnblogs.com/-pwl/p/13760783.html
Copyright © 2020-2023  润新知