题目描述
Description
给定n个整数in和目标值T,求某一非空子集使 子集的元素的和 与 目标值之差 的绝对值最小,元素可重复
输入描述
Input Description
第一行为整数n T
n为整数个数,T为目标值
第二行为n个整数in
输出描述
Output Description
一个整数d,为差的最小值的绝对值
样例输入
Sample Input
5 9
1 1 1 4 17
样例输出
Sample Output
2
数据范围及提示
Data Size & Hint
1<=n<=101
0<=T<=2147483647
0<=in<=2147484647
放心,n很大的时候数据都很弱…
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
/* 这个题纯用背包做会超空间的,因为目标值太大了,而且题目说目标值大的时 候n会很小,所以分情况讨论,当目标值很大时,用dfs,否则用背包 */ #include<cstdio> #include<iostream> #include<cstdlib> #define ll long long #define M 10000010 #define N 110 using namespace std; bool f[M]; ll n; ll sum,ans,v[M],goal; void dfs(int t,ll tot) { ans=min(ans,(ll)abs(tot-goal)); if(t>n)return; if(goal<tot)return; dfs(t+1,tot); dfs(t+1,tot+v[t]); } int main() { cin>>n;cin>>goal; for(int i=1;i<=n;i++) cin>>v[i],sum+=(ll)v[i]; ans=sum; if(sum<=goal)printf("%lld",(ll)abs(sum-goal)); else if(sum<=M-10) { f[0]=1; for(int i=1;i<=n;i++) for(ll j=sum;j>=v[i];j--) if(f[j-v[i]])f[j]=1; for(ll i=0;i<=sum;i++) if(f[i])ans=min(ans,(ll)abs(i-goal)); printf("%lld",ans); } else { dfs(1,0); printf("%lld",ans); } return 0; }