7.1 深搜-子集和问题 (枚举子集+剪枝)
Posted cxs070998
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了7.1 深搜-子集和问题 (枚举子集+剪枝)相关的知识,希望对你有一定的参考价值。
---恢复内容开始---
7.1,今日AC题目5到,今天为大家讲解一道普及组的深搜剪枝问题,这道题参解时需要在脑海及对应的手上模拟,切忌眼高手低,切忌三心二意
题目描述
对于一个给定正整数的集合s=x1,x2,x3…xn和正整数c,编程计算s的第一个子集s1,使得子集s1的和等于c。
输入
第一行有2个正整数n和c
第二行有n个正整数
n<7000,c<maxlongint
第二行有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金级段位,信息学竞赛,传统算法高级人才稀缺,高级教育人才有价无市,咸鱼翻身的机会就在眼前,哪怕只有一次机会,都应全力以赴
如今的我只能辅导入门组,而入门组能辅导的人太多了,争取在暑假尽快提升自我,将普及组的题刷完,辅导普及组,提升自我在第一位,挣钱在第二位,要挣就挣个大的。
博观而约取,厚积而薄发。
---恢复内容结束---
以上是关于7.1 深搜-子集和问题 (枚举子集+剪枝)的主要内容,如果未能解决你的问题,请参考以下文章