1 条题解

  • 0
    @ 2025-5-5 21:02:49

    算法标签

    图论(并查集思想用于处理簇之间的关系)、贪心算法(贪心的思想在于每次都尽可能地将文件簇移动到最优位置)、模拟(模拟磁盘簇的移动操作)

    题解分析

    1. 首先从输入中读取磁盘簇的总数 和文件的数量 ,同时获取每个文件占用的簇数量以及对应的簇号。可以使用合适的数据结构来存储这些信息,例如使用一个二维数组来记录每个文件所占用的簇号列表。

    2. 创建一个数组用于记录每个簇当前对应的目标簇号。这里运用并查集的思想来维护这些簇之间的逻辑关系,通过并查集可以方便地找到某个簇最终应该归属的目标簇(即最优排列下的位置)。并查集的初始化是将每个簇的父节点设为自身。

    3. 检查当前的磁盘簇排列是否已经是最优排列,也就是检查每个被占用的簇的当前位置和目标位置是否一致。可以通过遍历所有被占用的簇,对比其当前位置和目标位置来实现。

    4. 如果不是最优排列,就需要找到一个被占用且位置不正确的簇。可以通过遍历所有被占用的簇来找到这样的簇。然后将该簇移动到一个空闲的簇位置,这里运用贪心算法的思想,每次都选择将簇移动到能使整体排列更接近最优的空闲位置。在移动簇之后,需要更新并查集来反映簇之间关系的变化,同时更新相关的记录,如目标簇号数组等。

    5. 重复步骤 4,不断地移动簇,直到所有的文件簇都处于最优位置,即所有被占用的簇的当前位置和目标位置都一致为止。

    示例代码(C++)

    
    #include <iostream>
    #include <string.h>
    using namespace std;
    
    int clusterMove[10010];                // clusterMove[i]=j: i-->j
    int cluster[10010];                   // cluster[i]=j: 第i个要处理的是j号块 
    bool vis[10010];
    int N, K, S;
    
    void dfs(int k)
    {
        int l = clusterMove[k];            // k-->l
        vis[k] = true;
        // 若l空闲 
        if (clusterMove[l] == 0)
        { 
            cout << k << " " << l << endl;
            clusterMove[l] = l;
            clusterMove[k] = 0;
        }
        else
        {
            if (vis[l])
            {
                // 若存在环,破之 
                for (int i = N; i >= 1; i--)
                {
                    if (clusterMove[i] == 0)
                    {
                        cout << k << " " <<  i << endl;
                        clusterMove[i] = l;    // i-->l
                        clusterMove[k] = 0;    // 第k个cluster空余 
                        cluster[l] = i;       // 第l个要处理的cluster由k改为i 
                        break;
                    }
                }
            }
            else 
            {
                // 递归将l移走 
                dfs(l);
                // 将l移走后,再k-->l 
                cout << k << " " << l << endl;    // k-->l
                clusterMove[k] = 0;
                clusterMove[l] = l;
            }
            
        }
    
    }
    
    int main()
    {
        while (cin >> N >> K)
        {
            memset(clusterMove, 0, sizeof(clusterMove));
            
            int cnt = 0;
            bool needed = false;
            for (int i = 0; i < K; i++)
            {
                cin >> S;
                int t;
                for (int j = 0; j < S; j++)
                {
                    cin >> t;
                    clusterMove[t] = ++cnt;    // t-->cnt
                    cluster[cnt] = t;
                    if (t != cnt)
                    {
                        needed = true;
                    }
                }
            }
            
            if (!needed)
            {
                cout << "No optimization needed" << endl;
                continue;
            }
            for (int i = 1; i <= cnt; i++)
            {
                if (clusterMove[i] != i)
                {
                    memset(vis, false, sizeof(vis));
                    dfs(cluster[i]);
                }
            }
        }
        return 0;
    }
    
    
    • 1

    信息

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