7.1 深搜-子集和问题 (枚举子集+剪枝)

---恢复内容开始---

7.1,今日AC题目5到,今天为大家讲解一道普及组的深搜剪枝问题,这道题参解时需要在脑海及对应的手上模拟,切忌眼高手低,切忌三心二意

题目描述

对于一个给定正整数的集合s={x1,x2,x3…xn}和正整数c,编程计算s的第一个子集s1,使得子集s1的和等于c。

输入

第一行有2个正整数n和c
第二行有n个正整数
n<7000,c<maxlongint

输出

一行数据,按输入的顺序输出,若无解则输出"No Solution!"

样例输入

5 10
2 2 6 5 4

样例输出

2 2 6

题解:  这道题的基本解题思想是用dfs枚举数组,计算数组的和。  但若是数据较大耗时较长,我们便须用剪枝来优化,对应的剪枝方法:    1.计算出后缀和数组sum[i]和后缀最小值数组mina[i]    2.对于sum[i]数组,在枚举过程中若是当前数组和cnt加上i的后缀和sum[i]小于c,则直接break跳出循环,当前dfs状态结束    3.对于mina[i]数组,在枚举过程中若是当前数组和cnt加上mina[i]>c,也是直接跳出循环,当前dfs状态结束,跳入下一状态

题解代码:

#include<iostream>#include<string>using namespace std;int n;long long c,a[7005],sum[7005],mina[7005],ans[7005],minn=0x3f3f3f3f,sum1=0;bool flag=0;void dfs(int index1,int index2,int cnt){ if(cnt>c) return ; if(cnt==c){  for(int i=0;i<index2;i++){   printf("%lld ",ans[i]);  }printf("\n");  exit(0); }  for(int i=index1+1;i<n;i++){  if(cnt+sum[i]<c) break;  if(cnt+mina[i]>c) break;   ans[index2]=a[i];  dfs(i,index2+1,cnt+ans[index2]); }}int main(){ freopen("setsum.in","r",stdin); scanf("%d%lld",&n,&c); for(int i=0;i<n;i++){  scanf("%lld",&a[i]); } for(int i=n-1;i>=0;i--){  minn=min(minn,a[i]);  sum1+=a[i];  sum[i]=sum1;  mina[i]=minn; } /* for(int i=0;i<n;i++){  printf("%lld %lld\n",sum[i],mina[i]); } */ dfs(-1,0,0); printf("No Solution!\n");  return 0; }

反省与展望:  7.1日记住这一天,正如孙老师所说:追求卓越,成功便会在不经意间与你相遇  当今段位usaco青铜,坚持每天进步一点点,哪怕多刷一道题,多学10分钟英语,与樊浩,李俊辉大佬共同进步,争取早日超过孙西越大佬  争取早日拿下usaco金级段位,信息学竞赛,传统算法高级人才稀缺,高级教育人才有价无市,咸鱼翻身的机会就在眼前,哪怕只有一次机会,都应全力以赴  如今的我只能辅导入门组,而入门组能辅导的人太多了,争取在暑假尽快提升自我,将普及组的题刷完,辅导普及组,提升自我在第一位,挣钱在第二位,要挣就挣个大的。  博观而约取,厚积而薄发。

---恢复内容结束---

原文地址:https://www.cnblogs.com/cxs070998/p/11117549.html

时间: 2024-10-07 22:53:00

7.1 深搜-子集和问题 (枚举子集+剪枝)的相关文章

hdu 1518 Square 深搜,,,,花样剪枝啊!!!

Square Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 9588    Accepted Submission(s): 3127 Problem Description Given a set of sticks of various lengths, is it possible to join them end-to-end

UVALive 2403 77377解题报告(深搜)

题意:给你一些固定的字符串,在给出数字,根据键盘的对应关系,输出所有的满足条件的字符串,输出顺序无所谓. 思路:因为题目说了,输出比较小,说明测试数据并不强,所以可以暴力回溯求出答案,将所有的给出的字符串压缩为数字,再将对应相同数字的字符串存储起来(当时忘了这里,WA了几次),然后深搜即可. 注意:多个字符串有可能对应相同的数字,需要另外存储,在深搜的时候,枚举这个符合条件的字符串. 代码如下: #include<iostream> #include<cstdio> #includ

POJ 2676 挺复杂的一道深搜

这道题之前就做了,一直没写题解,很不错的一道深搜题.这道题没什么剪枝优化,思路就是将空白格子的位置放入一个数组,然后用dfs尝试每个空白格子所放的数字. Sudoku Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 15861   Accepted: 7753   Special Judge Description Sudoku is a very simple task. A square table with 9 ro

HDU 3720 深搜 枚举

DES:从23个队员中选出4—4—2—1共4种11人来组成比赛队伍.给出每个人对每个职位的能力值.给出m组人在一起时会产生的附加效果.问你整场比赛人员的能力和最高是多少. 用深搜暴力枚举每种类型的人选择情况.感觉是这个深搜写的很机智. 在vector中存结构体就会很慢.TLE.直接存序号就AC了.以后还是尽量少用结构体吧. #include<stdio.h> #include<string.h> #include<map> #include<vector>

7.5 深搜-最佳调度问题(枚举排列+回溯+剪枝)

这几天偷了几天懒,今天为大家讲解一篇深搜好题,典型的全排列问题需运用剪枝+回溯来优化运行时间,与上一道都是比较典型的深搜优化问题. 题目描述 假设有n个任务由k个可并行工作的机器完成,完成任务i需要的时间为ti,对任意给定的整数n和k,以及完成任务i需要的时间ti,设计一个算法,求完成这n个任务的最佳调度,使得完成全部任务的时间最早. 输入 第一行有2个正整数n和k,第二行有n个正整数,表示ti n<7000,c<maxlongin 输出 一个整数,输出最早时间 样例输入 7 3 2 14 4

(暴力+深搜)POJ - 2718 Smallest Difference

原题链接: http://poj.org/problem?id=2718 题意: 给你几个数字,可以分成两个子集,然后分别按一定顺序排列组成一个数,求出这两只值差的绝对值的最小值. 分析: 反正也是刷着玩,果断先交一波全排列枚举的代码,果断TLE,然后开始想正解. 稍微想想,既然要差最小,肯定是两个数各一半.所以只要深搜出所有n/2(n为给定数字的个数)的组合,另外个n-n/2个数就有了. 但是枚举出来后的操作又想了很久,想过很多算法,都不怎么满意,最终用二分解决. 先把n/2和n-n/2全排列

hdu1455 Sticks 深搜 强剪枝

Sticks Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6035    Accepted Submission(s): 1704 Problem Description George took sticks of the same length and cut them randomly until all parts becam

poj1190 生日蛋糕(深搜+剪枝)

题目链接:poj1190 生日蛋糕 解题思路: 深搜,枚举:每一层可能的高度和半径 确定搜索范围:底层蛋糕的最大可能半径和最大可能高度 搜索顺序:从底层往上搭蛋糕,在同一层尝试时,半径和高度都是从大到小试 剪枝: ①已建好的面积已经超过目前求得的最优表面积,或者预见到搭完后面积一定会超过目前最优表面积,则停止搭建(最优性剪枝) ②预见到再往上搭,高度已经无法安排,或者半径无法安排,则停止搭建(可行性剪枝) ③还没搭的那些层的体积,一定会超过还缺的体积,则停止搭建(可行性剪枝) ④还没搭的那些层的

POJ 1129-Channel Allocation(四色定理+迭代深搜)

题目链接:传送门 题意:n个信号站,给出连接情况,要用信号覆盖所有信号站,要求相连的信号站不能用同一个信号. 等价问题==无向图染色==四色定理(每个平面地图都可以只用四种颜色来染色,而且没有两个邻接的区域颜色相同.已证明) 思路:深搜一条路(枚举颜色,判断当前点用已有的颜色能不能染,如不能则加一种颜色,判断强判就行了),搜到头答案就出来了..然后返回就可以了 注意单复数.. #include <algorithm> #include <iostream> #include <