题目描述 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很大的时候数据都很弱……
出题人还算有点良心,
就是取2倍的t,跑01背包就好,不过大数据我是搜的
#include<iostream>
#include<cstdio>
#include<cmath>
#include<map>
#define MAXN 1001
#define MAXM 20001
using namespace std;
long long n,m,ans=1e18,v[MAXN],min1=1e18,f[MAXM*100];
void dfs(long long t,long long tot)
{
if(t==n+1)
{
long long x=abs(m-tot);
ans=min(ans,x);
return;
}
dfs(t+1,tot);
dfs(t+1,tot+v[t]);
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>v[i],min1=min(min1,v[i]);
if(!m) {
ans=min1;
printf("%lld",ans);return 0;
}
if(n<=20)
{
dfs(1,0);
printf("%lld",ans);
return 0;
}
for(int i=1;i<=n;i++)
for(long long j=2*m;j>=v[i];j--)
f[j]=max(f[j],f[j-v[i]]+v[i]);
for(int i=1;i<=2*m;i++)
{
long long x=abs(f[i]-m);
ans=min(ans,x);
}
if(!m) ans=min1;
printf("%lld",ans);
return 0;
}