SOJ 4116: Chocolate

本文针对一个具体的编程问题——如何在有限的空间内放置数量最多的巧克力,提供了详细的算法思路及实现代码。通过枚举和背包算法,确保空间利用最大化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:

http://cstest.scu.edu.cn/soj/problem.action?id=4116


题目大意:

给你N块宽度为1、长度不等的巧克力。

再给你一个1*L的盒子。

问最少放进去多少块巧克力,就使得剩下的巧克力一块都放不进去了。


算法:

首先枚举没有放进盒子的巧克力中,长度最短的是哪块。

也就是说,盒子里的任一个间隔,都不可能大于这块巧克力的长度,且至少有一个间隔的长度严格小于它。

这样你从每个间隔里分出一点点到最短的那个间隔里,就可以保证每个间隔都放不下剩下的那些巧克力了。
既然枚举的是没有放进盒子的巧克力中最短的是那块,那么比它的短的巧克力就必须全部在盒子里。
除此之外,如果巧克力之间的间隔还是太大,就要从剩下的巧克力中再放一些进去。做个背包就可以了。
也就是说从剩下的巧克力中选取尽量少的,使得巧克力间的间隔达到要求,当然还有一个前提是这些巧克力有足够的空间能被放进去。


代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <cstdlib>
#include <cstring>
#include <string>
#include <climits>
#include <cmath>
#include <queue>
#include <vector>
#include <stack>
#include <set>
#include <map>
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;

const int MAXN = 50;
const int MAXM = 1100;
int a[MAXN];
int d[MAXM];

int main()
{
    int cas;
    scanf("%d", &cas);
    for (int T =1; T <= cas; T ++)
    {
        int n, l;
        scanf("%d %d", &l, &n);
        for (int i = 0; i < n; i ++)
        {
            scanf("%d", &a[i]);
        }
        sort(a, a + n);
        int ans = n;
        int tmp = 0;
        for (int i = 0; i < n; i ++)
        {
            int ret = tmp + (i + 1) * a[i];
            memset(d, -1, sizeof(d));
            d[0] = 0;
            for (int j = i; j < n; j ++)
            {
                for (int k = 1000 - a[j]; k >= 0; k --)
                {
                    if (d[k] != -1)
                    {
                        d[k + a[j]] = (d[k + a[j]] == -1) ? d[k] + 1 : min(d[k+a[j]], d[k] + 1);
                    }
                }
            }
            for (int j = 0; j <= 1000; j ++)
            {
                if (d[j] != -1)
                {
                    if (j + tmp <= l && d[j] * a[i] + j + ret > l)
                    {
                        ans = min(ans, i + d[j]);
                    }
                }
            }
            tmp += a[i];
        }
        printf("%d\n",ans);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值