UVA ~ 624 ~ CD (DFS+剪枝)

题意:给你一个数字N,然后给你k,后面有k个数字,要用这k个数字凑出来最接近N但是不超过N的数字。

思路:我们直接搜索,传两个参数,一当前累加和,二当前选到了哪个数字。外面开一个标记数组,标记该数字有没有被选过。

全局维护一个最大值MAX,当MAX被更新时,我们把此时选择的数字存到ans数组里面。

为什么要传当前选到了哪个数字呢,这是一个剪枝,没有该剪枝会超时。当我们选到第二个数字的时候没必要再往前挑选数字了,因为第二个数字和第一个数字的组合一定在选择第一个数字的情况下包括。

题目好像说这些数字的大小在int范围内,但是用01背包能水过,估计是数据水把。

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 25;
int v, n, a[MAXN], ans[MAXN], MAX, cnt;
bool vis[MAXN];
void dfs(int sum, int r)
{
    if (sum > MAX)
    {
        MAX = sum; cnt = 0;
        for (int i = 0; i < n; i++)
        {
            if (vis[i]) ans[cnt++] = a[i];
        }
    }
    for (int i = r; i < n; i++)
    {
        if (!vis[i] && sum + a[i] <= v)
        {
            vis[i] = true;
            dfs(sum + a[i], i + 1);
            vis[i] = false;
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    while (cin >> v >> n)
    {
        memset(vis, 0, sizeof(vis));
        MAX = 0;
        for (int i = 0; i < n; i++) cin >> a[i];
        dfs(0, 0);
        long long t = 0;
        for (int i = 0; i < cnt; i++)
        {
            printf("%d ", ans[i]);
            t += ans[i];
        }
        printf("sum:%d\n", t);
    }
    return 0;
}
/*
5 3 1 3 4
10 4 9 8 4 2
20 4 10 5 7 4
90 8 10 23 1 2 3 4 5 7
45 8 4 10 44 43 12 9 8 2
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值