hdu 4112 Break the Chocolate(模拟)

本文探讨了一个有趣的算法问题:如何将一块三维巧克力通过手掰或刀切的方式最快地分成单位体积的小块。文中提供了两种实现方式的代码示例,并对比了不同方法的效率。

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

题意是给一个N*M*K的立方体巧克力,求分别用手掰和用刀切将其分为 1 * 1 * 1的小立方体最少的步骤数。


开始的时候一点思路都没有,接下来带入数字开始死算。

当巧克力为平面时:eg.1。      2 * 2 的巧克力手掰需要 2 * 2 -1 步;刀切需要  log2(2 * 2) = 2 步。

                                      2。     5 * 4的巧克力手掰需要 5 * 4 - 1 步;刀切需要 log2 (5 * 4)取上界 = 5 步。

推广到立体,结论为:手掰需要 N * M * K - 1 步, 刀切需要 log2 (N * M *K )取上界步。

由于log2 (N * M *K )中 N * M *K比较大,所以利用数学公式将其缩小:log2 (N * M *K ) = log2(N) + log2(M) + log2(K)。


刚开始的时候没注意到这里,打表打大了。


代码:

#include <stdio.h>

__int64 log2[] = {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384};

int knife(int x)
{
    for (int i = 0; i < 15; i++)
    {
        if (x == log2[i])
        {
            x = i;
            break;
        }
        if (x > log2[i] && x < log2[i + 1])
        {
            x = i + 1;
            break;
        }
    }
    return x;
}

int main()
{
    /*freopen("out.txt", "w", stdout);
    long long num = 1;
    int count = 0;
    for (int i = 0; i < 100; i++)
    {
        num *= 2;
        printf("%lld,", num);
        count ++;
        if (num >= 8000000000)
        {
            printf("\n\n%d", count);
            break;
        }
    }*/
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
#endif // LOCAL
    int ncase;
    scanf("%d", &ncase);
    for (int i = 1; i <= ncase; i++)
    {
        printf("Case #%d:", i);
        __int64 N, M, K;
        scanf("%I64d%I64d%I64d", &N, &M, &K);
        __int64 ans = N * M * K;
        printf(" %I64d ", ans - 1);
        ans = knife(N) + knife(M) + knife(K);
        printf("%I64d\n", ans);
    }
    return 0;
}

另一种写法:

#include <cstdio>

typedef __int64 LL;

int knife(int x) {
    int tmp = 0;
    while (x != 1) {
        if (x&1)
           x++; //x 为奇数时加一为偶数 如: 7/2 = 3 其实应该二分 4
        x /= 2;
        tmp++;
    }
    return tmp;
}

int main() {
    #ifdef LOCAL
    freopen("in.txt","r",stdin);
    #endif // LOCAL
    int tcase, cc = 1;
    scanf("%d", &tcase);
    while (tcase--) {
        LL n, m, k;
        scanf("%I64d%I64d%I64d", &n, &m, &k);
        int tt = knife(n) + knife(m) + knife(k);
        printf("Case #%d: %I64d %d\n", cc++, m*n*k - 1, tt);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值