链接:点击打开链接
题意:给出n个数,要求选出一些数加和使得加和最接近D,要求加和的过程中和不等大于等于2
代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
int a[205],dp[250005];
int main(){ //将范围变正后并扩大
double D,num; //dp[i]表示能否组成i
int t,n,i,j,ans,tmp,shift;
scanf("%d",&t);
while(t--){
shift=200000;
scanf("%lf%d",&D,&n);
if(D>0) //这个题精度卡的特别严,一定要注意精度
tmp=(int)(D*10000+1e-8)+shift;
else
tmp=(int)(D*10000-1e-8)+shift;
for(i=0;i<n;i++){
scanf("%lf",&num);
if(num>0)
a[i]=(int)(num*10000+1e-8);
else
a[i]=(int)(num*10000-1e-8);
}
sort(a,a+n);
memset(dp,0,sizeof(dp));
dp[shift]=1;
for(i=0;i<n;i++){
if(a[i]>0){ //注意不能等于220000
for(j=220000-1-a[i];j>=0;j--)
if(dp[j])
dp[j+a[i]]=1;
}
else{
for(j=-a[i];j<220000;j++)
if(dp[j])
dp[j+a[i]]=1;
}
}
ans=-1;
for(i=0;;i++){ //找差值是否存在,如果存在两个值则输出小的那个
if(tmp-i>=0&&dp[tmp-i]){
ans=tmp-i;
break;
}
if(tmp+i<220000&&dp[tmp+i]){
ans=tmp+i;
break;
}
}
printf("%.4lf\n",(ans-shift)*1.0/10000);
}
return 0;
}