题意:给你一个数字N,然后给你k,后面有k个数字,要用这k个数字凑出来最接近N但是不超过N的数字。
思路:我们直接搜索,传两个参数,一当前累加和,二当前选到了哪个数字。如果只传一个参数,当前累加的然后挑选数字每次都从第一个找会超时。所以传两个参数。
外面开一个标记数组,标记该数字有没有被选过。
全局维护一个最大值MAX,当MAX被更新时,我们把此时选择的数字存到ans数组里面。
为什么要传当前选到了哪个数字呢,这是一个剪枝,没有该剪枝会超时。当我们选到第二个数字的时候没必要再往前挑选数字了,因为第二个数字和第一个数字的组合一定在选择第一个数字的情况下包括。
#include<stdio.h>
int flag[100000];
int n,k,maxn,ans,u;
int a[100000],s[100000];
void dfs(int x,int y)
{
if(x > maxn)
{
maxn = x;
u = 0;
for(int i = 0 ; i < n ; i++)
{
if(flag[i])
{
s[u++] = a[i];
}
}
}
for(int i = y ; i < k ; i++)
{
if(!flag[i] && (a[i] + x) <= n)
{
flag[i] = 1;
dfs(x + a[i],i + 1);
flag[i] = 0;
}
}
}
int main()
{
while(~scanf("%d",&n))
{
scanf("%d",&k);
for(int i = 0 ; i < k ; i++)
{
scanf("%d",&a[i]);
}
maxn = -1,ans = 0,u = 0;
dfs(0,0);
for(int i = 0 ; i < u ; i++)
{
printf("%d ",s[i]);
}
printf("sum:%d\n",maxn);
}
}