Codevs 1692 子集和的目标值

11 篇文章 1 订阅

题目描述 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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值