【算法题】切割木材

问题如图:
这里写图片描述

:木头不一定都要用,用也不一定都要用完

  1. 问题可以转化成在1和给的所有原木中最长的长度中间找一个合适的长度,使得把每段原木按此分段后得到的小段木头数目至少为k:在1—max之间用折半查找,找到最大的长度
//def woodCut(self, L, k){
//  if sum(L) < k :
//  return 0
//
//      start, end = 1, max(L)
//      while start + 1 < end :
//          mid = start + (end - start) / 2
//          pieces = sum([l / mid for l in L])
//          if pieces >= k :
//              start = mid
//          else :
//          end = mid
//
//          if sum([l / end for l in L]) > k:
//  return end
//      return start
//}
#include <stdio.h>
#include <numeric>

using namespace std;

int k(0);
int array[10000];
int len(0), max_wood(0);

int WoodCut()//二分查找上界
{
    int sum = accumulate(array, array+len,0);
    if (sum < k)
        return 0;

    int left(1), right(max_wood);
    int mid;
    while (left+1<right)
    {
        mid = left + (right - left) / 2;
        int k_tmp(0);

        for (auto i = 0; i <= len ;i++)
        {
            k_tmp += array[i] / mid;
        }

        if (k_tmp>=k)
        {
            left = mid;
        }
        else
        {
            right = mid;
        }
    }
    int right_k(0);
    for (auto i = 0; i <= len; i++)
    {
        right_k += array[i] / right;
    }
    if (right_k>=k)
    {
        return right;
    }
    else
    {
        return left;
    }

    return 0;
}

int main()
{
    char c;
    scanf("%d", &k);
    while (1)
    {
        scanf("%d", &array[len]);
        if (array[len]>max_wood  )
        {
            max_wood = array[len];
        }
        c = getchar();
        if (c=='\n')
        {
            break;
        }
        ++len;
    }
    printf("%d",WoodCut());

    return 1;
}
分支算法求解条形板材切割通常用于优化材料利用,例如在剪切金属板、木材等,使得切割后的废料最少。这里我们可以使用一种名为"动态规划+回溯法"的策略,其中分治法是核心思想。 伪代码如下: ```python function cutBoard(boardWidth, boardHeight, minCut): if boardWidth <= 0 or boardHeight <= 0: return "Invalid dimensions" # 初始化二维数组 dp[i][j] 表示宽度 i 和高度 j 的最小切割数 dp = [[0 for _ in range(boardHeight + 1)] for _ in range(boardWidth + 1)] # 动态规划过程 for i in range(1, boardWidth + 1): for j in range(1, boardHeight + 1): # 如果可以直接切割,取最小值 dp[i][j] = dp[i - 1][j] + 1 # 否则考虑从上边和左边切割 if i >= j: dp[i][j] = min(dp[i][j], dp[i - j][j] + dp[j][j]) # 回溯找到最优方案 solution, cuts = backtracking(dp, boardWidth, boardHeight, minCut) return solution, cuts function backtracking(dp, width, height, minCut): if width == 0 or height == 0: return [], 0 bestCut = dp[width][height] if bestCut > minCut: return None, -1 # 记录路径并返回最小切割次数和方案 path, currentCuts = backtrack_helper(dp, width, height, [], minCut) return path, currentCuts function backtrack_helper(dp, x, y, path, minCut): # 添加当前位置到路径 path.append((x, y)) # 如果当前位置无法继续切割,结束此路径 if dp[x][y] == dp[x - 1][y]: return path, currentCuts # 探索所有可能的方向 for dx, dy in [(1, 0), (0, 1)]: # 上下方向 nextCuts = dp[x][y] - dp[x - dx][y - dy] newPath, newCuts = backtrack_helper(dp, x - dx, y - dy, path.copy(), minCut) if newCuts is not None and newCuts + currentCuts <= minCut: return newPath, newCuts + currentCuts return path, currentCuts ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值