文章

8

粉丝

0

获赞

42

访问

1.5k

头像
只通过了75%,不知道为什么
P1154 清华大学上机题
发布于2025年3月20日 14:44
阅读数 103

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main() {
    int n, m;
    while (cin >> n) {
        vector<ll> agent;
        vector<ll> sever;
        int a, b, c, d;

        // 读取代理服务器 IP
        for (int i = 0; i < n; i++) {
            scanf("%d.%d.%d.%d", &a, &b, &c, &d);
            // 使用位移来表示 IP
            ll temp = (a * 1000000000) + (b * 1000000) + (c * 1000) + d;
            agent.push_back(temp);
        }

        cin >> m; // 读取目标服务器的数量
        // 读取目标服务器 IP
        for (int i = 0; i < m; i++) {
            scanf(&quo...

登录查看完整内容


登录后发布评论

2 条评论
admin SVIP
2025年3月20日 15:29

算法时间复杂度高了导致超时

问题分析:我们需要在访问一系列目标服务器时,使用代理服务器,避免使用与目标服务器相同IP的代理。每次切换代理的次数应尽可能少。
动态规划优化:使用动态规划来记录每一步的最小切换次数,但需要将时间复杂度从O(mn^2)优化到O(mn)。

修改代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int main() {
    int n, m;
    while (cin >> n) {
        vector<ll> agents;
        vector<ll> servers;

        // 读取代理服务器IP
        for (int i = 0; i < n; ++i) {
            int a, b, c, d;
            scanf("%d.%d.%d.%d", &a, &b, &c, &d);
            agents.push_back((ll)a * 1000000000 + b * 1000000 + c * 1000 + d);
        }

        cin >> m;
        // 读取目标服务器IP
        for (int i = 0; i < m; ++i) {
            int a, b, c, d;
            scanf("%d.%d.%d.%d", &a, &b, &c, &d);
            servers.push_back((ll)a * 1000000000 + b * 1000000 + c * 1000 + d);
        }

        // 处理特殊情况:没有目标服务器需要访问
        if (m == 0) {
            cout << 0 << endl;
            continue;
        }

        // dp[i][j] 表示处理到第i个目标服务器,使用第j个代理的最小切换次数
        vector<vector<int>> dp(m, vector<int>(n, INT_MAX));

        // 初始化第一个目标服务器的处理情况
        bool hasValid = false;
        for (int j = 0; j < n; ++j) {
            if (agents[j] != servers[0]) {
                dp[0][j] = 0;  // 初始选择代理j,切换次数为0
                hasValid = true;
            }
        }
        if (!hasValid) {
            cout << -1 << endl;
            continue;
        }

        // 动态规划处理后续服务器
        for (int i = 1; i < m; ++i) {
            // 计算前一层的最小切换次数
            int prevMin = INT_MAX;
            for (int j = 0; j < n; ++j) {
                if (dp[i-1][j] < prevMin) {
                    prevMin = dp[i-1][j];
                }
            }
            if (prevMin == INT_MAX) {
                // 无法继续处理
                hasValid = false;
                break;
            }

            // 更新当前层的状态
            for (int j = 0; j < n; ++j) {
                if (agents[j] == servers[i]) {
                    dp[i][j] = INT_MAX;  // 不可用
                } else {
                    int option1 = dp[i-1][j];  // 不切换的情况
                    int option2 = prevMin + 1; // 切换的情况
                    dp[i][j] = min(option1, option2);
                }
            }

            // 检查当前层是否有可行解
            bool currentValid = false;
            for (int j = 0; j < n; ++j) {
                if (dp[i][j] != INT_MAX) {
                    currentValid = true;
                    break;
                }
            }
            if (!currentValid) {
                hasValid = false;
                break;
            }
        }

        if (!hasValid) {
            cout << -1 << endl;
            continue;
        }

        // 找到最后一个服务器的所有代理中的最小切换次数
        int minSwitches = INT_MAX;
        for (int j = 0; j < n; ++j) {
            if (dp[m-1][j] < minSwitches) {
                minSwitches = dp[m-1][j];
            }
        }

        cout << (minSwitches == INT_MAX ? -1 : minSwitches) << endl;
    }
    return 0;
}

 

赞(1)

sheep276 : 回复 admin: 懂了,感谢

2025年3月20日 18:59