1 条题解

  • 0
    @ 2025-5-20 13:40:48

    解题思路

    问题分析:我们需要在77小时(420420分钟)内尽可能多地参观不同的博物馆。每个博物馆有一个参观时间,从一个博物馆到另一个博物馆有一个交通时间。我们需要找到一条路径,使得总时间(参观时间 + 交通时间)不超过420420分钟,且参观的博物馆数量最多。

    状态表示:使用动态规划(DPDP)来解决这个问题。状态dp[mask]dp[mask]表示在已经访问了maskmask所代表的博物馆集合后,剩余的最大时间。maskmask是一个二进制数,第ii位为11表示第ii个博物馆已经被访问。

    初始化:对于每个博物馆,如果其参观时间不超过420420分钟,则初始化dp[1<<i]dp[1 << i] = 420cost[i]420 - cost[i],表示从该博物馆开始,剩余的时间。

    状态转移:对于每一个状态maskmask,尝试从未访问的博物馆中选择一个,计算从当前博物馆到该博物馆的交通时间,并更新新的状态mask(1<<i)mask | (1 << i)的剩余时间。如果剩余时间足够(即非负),则更新DPDP表。

    最优解:在DFSDFS过程中,记录访问的博物馆数量的最大值。

    优化:使用FloydFloyd算法预处理所有博物馆之间的最短路径,以减少交通时间的计算复杂度。

    解题方法

    Floyd算法预处理:计算所有博物馆之间的最短交通时间,存储在gg矩阵中。

    动态规划初始化:初始化dpdp数组为1-1,表示不可达。对于每个博物馆,如果其参观时间不超过420420分钟,则设置初始状态。

    深度优先搜索(DFS):从每个初始状态出发,尝试访问未访问的博物馆,更新状态,并记录最大访问数量。

    输出结果:对于每个测试用例,输出可以访问的博物馆的最大数量。

    C++代码实现:

    #include <ctime>
    #include <cmath>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <string>
    #include <vector>
    #include <deque>
    #include <list>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <numeric>
    #include <algorithm>
    #include <functional>
    using namespace std;
    const int maxn = 25;
    const int inf  = 0x3f3f3f3f;
    int g[maxn][maxn], cost[maxn];
    int dp[(1<<20)+10];
    int n;
    int ans;
     
    void floyd() {
        for(int k = 0; k < n; ++k) {
            for(int i = 0; i < n; ++i) {
                if(i == k) continue;
                for(int j = 0; j < n; ++j) {
                    if(j == k || i == j) continue;
                    g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
                }
            }
        }
        return ;
    }
     
    void dfs(int p, int c, int s) {
        if(ans == n) return ;
        if(ans < c) ans = c;
        if(dp[s] <= 0) return ;
        for(int i = 0; i < n; ++i) {
            if(!(s&(1<<i))) {
                if(dp[s] - g[p][i] - cost[i] < 0) continue;
                if(dp[s|(1<<i)] < dp[s] - g[p][i] - cost[i]) {
                    dp[s|(1<<i)] = dp[s] - g[p][i] - cost[i];
                    dfs(i, c + 1, s|(1<<i));
                }
            }
        }
        return ;
    }
     
     
    int main() {
     
        //freopen("aa.in", "r", stdin);
        while(scanf("%d", &n) && n) {
            for(int i = 0; i < n; ++i) {
                scanf("%d", &cost[i]);
            }
            for(int i = 0; i < n; ++i) {
                for(int j = 0; j < n; ++j) {
                    scanf("%d", &g[i][j]);
                }
            }
            floyd();
            memset(dp, -1, sizeof(dp));
            ans = 0;
            for(int i = 0; i < n; ++i) {
                if(cost[i] <= 420) {
                    dp[1<<i] = 420 - cost[i];
                    dfs(i, 1, 1<<i);
                }
            }
            printf("%d\n", ans);
        }
        return 0;
    }
    • 1

    信息

    ID
    1089
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    2
    已通过
    2
    上传者