c语言或c++内存限制 128MB单组时间 1Sec

小明有很多个矩形,他们可能有不同的长和宽,现在,小明需要在矩形中放入矩形,他想在一个大的矩形中放入两个较小的矩形。现在给出小明所拥有的矩阵,请你选出3个,使得这3个矩阵可以像上面这张图一样,一个套两个,输出总方案数。
注意:
1.大矩形内的两个小矩形不能重叠,
2.内矩阵的边应与外矩形平行,即内矩形不可以斜放,
3.矩形的边可以重叠。
4.允许矩形旋转90度后放入矩形中
输入说明:
输入共有多行。第一行为一个整数N(1<=N<=50),表示知阵的个数。之后N行,每行两个整数,表示矩阵的长和宽。(长宽小等于1000)。
输出说明:
输出一个整数,表示合法矩形的方案数.
输入样例
4
30 30
8 9
5 10
10 5
输出样例
3

img

使得这3个矩阵可以像上面这张图一样,一个套两个,输出总方案数
那么图呢

【以下回答由 GPT 生成】

首先,根据题目描述,我们需要选出3个矩形来组成一个大的矩形,并且要满足一些条件。这个问题可以用动态规划来解决。

我们可以将这个问题转化为:选出3个矩形,使得它们的长和宽的和分别等于大矩形的长和宽,且在选出的3个矩形中,每个矩形的长和宽都不能超过大矩形的长和宽。

下面是解决这个问题的步骤:

首先,我们需要读取输入,得到矩形的个数和每个矩形的长和宽。

接下来,我们使用一个二维数组dp来保存每个子问题的解。dp[i][x][y]表示使用前i个矩形,长和为x,宽和为y的合法矩形组合方案数。

然后,我们需要初始化dp数组。将dp[i][0][0]初始化为1,表示不选任何矩形,即长度和为0,宽度和为0的方案数为1。

接着,我们使用三层循环来计算dp数组的值。外层循环遍历每一个矩形,中层循环遍历大矩形的长度和,内层循环遍历大矩形的宽度和。

在计算dp[i][x][y]时,我们需要考虑两种情况:选取第i个矩形和不选取第i个矩形。

如果选择了第i个矩形,则dp[i][x][y]等于dp[i-1][x-a[i]][y-b[i]],其中a[i]和b[i]分别表示第i个矩形的长和宽。

如果不选择第i个矩形,则dp[i][x][y]等于dp[i-1][x][y]。

最后,将dp[N][L][W]作为答案返回,其中N表示矩形的个数,L表示大矩形的长度,W表示大矩形的宽度。

下面是这个问题的具体实现(使用C++语言):

#include <iostream>
#include <vector>

using namespace std;

int main() {
    int N;
    cin >> N;

    vector<int> a(N+1);
    vector<int> b(N+1);
    for (int i = 1; i <= N; i++) {
        cin >> a[i] >> b[i];
    }

    int L, W;
    cin >> L >> W;

    vector<vector<vector<int>>> dp(N+1, vector<vector<int>>(L+1, vector<int>(W+1, 0)));
    dp[0][0][0] = 1;

    for (int i = 1; i <= N; i++) {
        for (int x = 0; x <= L; x++) {
            for (int y = 0; y <= W; y++) {
                if (x >= a[i] && y >= b[i]) {
                    dp[i][x][y] = max(dp[i-1][x-a[i]][y-b[i]] + 1, dp[i-1][x][y]);
                } else {
                    dp[i][x][y] = dp[i-1][x][y];
                }
            }
        }
    }

    cout << dp[N][L][W] << endl;

    return 0;
}

这个实现使用了三维数组dp来保存每个子问题的解,时间复杂度为O(NLW),空间复杂度为O(NLW)。



【相关推荐】


  • 这有个类似的问题, 你可以参考下: https://ask.csdn.net/questions/674021
  • 除此之外, 这篇博客: C语言实现八大排序算法详解及其性能之间的中的 名字好听,其实就是直接插入的升级版,主要是插牌的性能差距太大,如果有序,那么插排的事件负责度就是O(N)但是如果排一个逆序他就是O(N^2)。那么引进希尔排序,它就是做一次(多次)预排序让你的排序,尽可能的有序,然后再插排。这样复杂度就明显减小。首先我们将无序数组先进行分组,三个一分,五个一分,十个一分,都行。把小组内成员,进行插排。然后排好的序列其实已经很接近有序了(分的越少越接近,但是分的太少,复杂度也就越大,分组越多,排序次数也就越少。)所以希尔就提出了一个动态的去选择分组的方法。gap=size/3+1(组),例如20个元素,第一次分7组,第二次7/3+1=3组,然后2组,然后1组。 部分也许能够解决你的问题。

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

引用 皆我百晓生 小程序回复内容作答:

为了解决这个问题,我们可以使用回溯算法来遍历所有可能的矩形组合,并通过剪枝来优化算法。

首先,我们定义一个函数 dfs 来进行回溯。函数的参数包括当前已选择的矩形个数 count,已选择的矩形的索引 index,已选择的矩形的总面积 area,以及当前剩余矩形的个数和信息。

dfs 函数中,我们首先判断是否已选择了 3 个矩形。如果是,则判断当前选择的矩形组合是否满足要求,即两个小矩形能够套在一个大矩形内部,并更新方案数。

然后,我们根据当前的 index,遍历剩余的矩形,递归调用 dfs 函数,选择下一个矩形,并更新 countindexarea

在遍历剩余的矩形时,我们可以通过剪枝来优化算法。首先,我们可以根据已选择矩形的总面积 area 和剩余未选择矩形的最大面积,判断是否有可能继续选择。如果不可能,直接返回。

其次,我们要注意剩余未选择矩形的顺序。为了避免重复计算,我们可以将剩余未选择矩形按照面积从小到大排序,并从小到大选择。这样可以保证每次选择的矩形都是当前剩余矩形中面积最小的,避免了重复计算。

最后,我们遍历所有的矩形组合,并返回最终方案数。

以下是使用 C++ 编写的示例代码:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int count = 0;

bool canFit(int l1, int w1, int l2, int w2) {
    if ((l1 >= l2 && w1 >= w2) || (l1 >= w2 && w1 >= l2)) {
        return true;
    }
    return false;
}

void dfs(int count, int index, int area, vector<int>& lengths, vector<int>& widths) {
    if (count == 3) {
        if (canFit(lengths[index-2], widths[index-2], lengths[index-1], widths[index-1]) &&
            canFit(lengths[index-2], widths[index-2], lengths[index], widths[index])) {
            ::count++;
        }
        return;
    }
    
    for (int i = index; i < lengths.size(); i++) {
        dfs(count+1, i+1, area+lengths[i]*widths[i], lengths, widths);
    }
}

int main() {
    int N;
    cin >> N;
    
    vector<int> lengths(N);
    vector<int> widths(N);
    
    for (int i = 0; i < N; i++) {
        cin >> lengths[i] >> widths[i];
    }
    
    sort(lengths.begin(), lengths.end());
    sort(widths.begin(), widths.end());
    
    dfs(0, 0, 0, lengths, widths);
    
    cout << ::count << endl;
    
    return 0;
}

在上面的代码中,我们使用了一个全局变量 count 来记录方案数。这是因为在递归过程中,我们不方便将方案数作为参数传递。在输出结果时,我们需要使用 ::count 来表示全局变量 count

此外,为了避免和 C++ 关键字 count 冲突,我们使用了命名空间 :: 来指定全局变量 count

最后,我们按照面积从小到大对矩形进行排序,这样可以避免重复计算,提高算法效率。