机试题——计网实验2.0

题目描述

小明需要为两台柜式路由器配备接口板,使得每台设备的接口板转发能力之和等于设备的整机转发能力。给定设备的整机转发能力、接口板数量以及接口板的转发能力列表,判断是否存在一种安装方法,使得两台设备的接口板转发能力之和分别等于整机转发能力。如果存在,则输出两台设备的接口板转发能力列表;如果不存在,则输出-1

输入描述

  1. 第一行:一个整数,表示设备的整机转发能力(单位:Gbps,范围:[1, 2000])。
  2. 第二行:一个整数num,表示客户订购的接口板数量(范围:[1, 200])。
  3. 第三行:num个整数,表示接口板的转发能力(单位:Gbps,范围:正整数)。

输出描述

如果存在满足要求的安装方法,分两行输出两台设备配置的接口板的转发能力列表,每台设备的接口板按转发能力从小到大排列。如果第一个接口板转发能力相同,则接口板数量多的优先输出。如果不存在对应的安装方案,则返回-1

用例输入

100
5
40 10 10 40 100
10 10 40 40
100

设备的整机转发能力为100,接口板转发能力分别为40, 10, 10, 40, 100。可以将10, 10, 40, 40分配给一台设备,100分配给另一台设备。

100
3
10 10 20
-1

解题思路

  1. 问题建模

    • 该问题可以看作是一个划分等和子集问题,目标是将接口板的转发能力划分为两个和相等的子集。
    • 使用动态规划(DP)解决该问题,判断是否存在一种划分方法。
  2. 动态规划

    • 定义dp[i][j]表示前i个接口板是否可以组成和为j的子集。
    • 初始化dp[0][0] = 1,表示空集可以组成和为0的子集。
    • 遍历每个接口板,更新dp数组。
  3. 回溯

    • 如果dp[num - 1][target]1,说明存在满足条件的划分方法。
    • dp数组中回溯,找到具体的划分方案。
  4. 输出结果

    • 按要求输出两台设备的接口板转发能力列表,每台设备的接口板按转发能力从小到大排列。
    • 如果不存在满足条件的划分方法,输出-1

代码

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;

void print_v(const vector<int>& res) {
    for (int i = 0; i < res.size(); i++) {
        cout << res[i];
        if (i < res.size() - 1) cout << " ";
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int target, num;
    int check = 0;
    cin >> target >> num;
    vector<int> nums(num);
    for (int i = 0; i < num; i++) {
        cin >> nums[i];
        check += nums[i];
    }
    if (check != 2 * target) {
        cout << "-1";
    } else {
        // 动态规划 前i个数能不能组成j
        vector<vector<int>> dp(num, vector<int>(target + 1, 0));
        dp[0][0] = 1;
        dp[0][nums[0]] = 1;
        for (int i = 1; i < num; i++) {
            for (int j = 0; j <= target; j++) {
                if (j >= nums[i]) {
                    // 选或不选
                    dp[i][j] = dp[i - 1][j - nums[i]] || dp[i - 1][j];
                }
            }
        }
        if (!dp[num - 1][target]) {
            cout << "-1";
        } else {
            vector<int> ans1, ans2;
            int cur = target;
            for (int j = num - 1; j >= 0; j--) {
                if (dp[j][cur] && cur > 0) {
                    // 选了
                    ans1.push_back(nums[j]);
                    cur -= nums[j];
                } else {
                    // 没选
                    ans2.push_back(nums[j]);
                }
            }
            sort(ans1.begin(), ans1.end());
            sort(ans2.begin(), ans2.end());
            if (ans1[0] == ans2[0]) {
                // 多的输出
                if (ans1.size() > ans2.size()) {
                    print_v(ans1);
                    cout << endl;
                    print_v(ans2);
                } else {
                    print_v(ans2);
                    cout << endl;
                    print_v(ans1);
                }
            } else if (ans1[0] < ans2[0]) {
                print_v(ans1);
                cout << endl;
                print_v(ans2);
            } else {
                print_v(ans2);
                cout << endl;
                print_v(ans1);
            }
        }
    }
    return 0;
}

你可能感兴趣的:(#,hw机试题,算法,数据结构,c++)