---恢复内容开始---
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