CCF-CSP 28次 第二题 【202212-2 训练计划】

方法一

// csp 202212-2 训练计划
// 100分
// 要注意一个节点可能回受到后面多个节点的影响
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>

using namespace std;

const int N = 370;

int n, m;
int rely[N], a[N];

int res[N], sum[N];  // res最早的时间, sum记录一条路径上累积的时间,用于判断是否超时
int st[N];  // 是否被依赖的  其实可以用哈希表去记录被哪些依赖
int ans[N]; // ans最迟的时间

int main()
{
    
    
    cin >> n >> m;
    
    for (int i = 1; i <= m; i ++ ) 
    {
    
    
        cin >> rely[i];
        st[rely[i]] = true; // 被依赖
    }
    
    for (int i = 1; i <= m; i ++ ) cin >> a[i];
        
    bool flag = true;    
    for (int i = 1; i <= m; i ++ )
    {
    
    
        if (!rely[i])
        {
    
    
            res[i] = 1;
            sum[i] = a[i];
        }
            
        else
        {
    
    
            int k = rely[i];
            res[i] = res[k] + a[k];
            
            sum[i] = sum[k] + a[i]; // 记录这条路径上累积的时间
        }
        
        if (sum[i] > n) flag = false;
    }
    
    for (int i = 1; i <= m; i ++ )
        cout << res[i] << ' ' ;
    cout << endl;
    
    if (flag)
    {
    
    
        for (int i = m; i >= 1; i -- ) // 从后往前
        {
    
    
            int temp = 400;
            for (int j = i + 1; j <= m; j ++ )
                if (rely[j] == i)
                    temp = min(temp, ans[j]);  
                    // 一个节点可能会受到后面多个节点的影响,要找到最小的依赖它的   
        
        if (temp == 400) 
            ans[i] = n - a[i] + 1;
        else 
            ans[i] = temp - a[i];
        }
        
        for (int i = 1; i <= m; i ++ )
            cout << ans[i] << " ";
    }
    // 错误
    // if (flag)
    // {
    
    
    //     for (int i = m; i >= 1; i -- )
    //         if (!st[i])  // 未被依赖
    //         {
    
    
    //             int k = a[i];
    //             int j = i;
                
    //             while (true)
    //             {
    
    
    //                 if (ans[j])
    //                     ans[j] = min(n - k + 1, ans[j]); // 出现更新,会进而影响前面的节点结果,不正确。
    //                 else 
    //                     ans[j] = n - k + 1;
                        
    //                 k += a[rely[i]];
    //                 j = rely[j];
    //                 if (j == 0) break;
    //             }
    //         }
                
    //     for (int i = 1; i <= m; i ++ )
    //         cout << ans[i] << " ";
    // }

    return 0;
}

方法二:求最晚时间采用DFS方法

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 370;

int n, m;
int rely[N], t[N];
int res[N], res2[N];
vector<int> g[N];

// 可以看成一棵树
void dfs(int u)
{
    
    
    if (g[u].size() == 0) 
    {
    
    
        res2[u] = n - t[u] + 1;
        return;
    }
    
    int minv = 400;
    for(auto i: g[u])
    {
    
    
        dfs(i);
        minv = min(minv, res2[i] - t[u]);
    }
    res2[u] = minv;
}

int main()
{
    
    
    cin >> n >> m;
    
    for (int i = 1; i <= m; i ++ )
    {
    
    
        cin >> rely[i]; // 每个节点依赖的节点
        g[rely[i]].push_back(i); // 每个节点的后序节点
    }

    for (int i = 1; i <= m; i ++ )
        cin >> t[i];
    
    bool flag = true;
    for (int i = 1; i <= m; i ++ )
    {
    
    
        if(rely[i] == 0) res[i] = 1; // 没有依赖
        else
            res[i] = res[rely[i]] + t[rely[i]];
        
        if (res[i] + t[i] - 1 > n) flag = false; // 超过最大天数
    }
    
    for (int i = 1; i <= m; i ++ )
        cout << res[i] << " ";
    cout << endl;
    
    // 可以继续计算最晚时间
    if (flag)
    {
    
    
        dfs(0);
        for (int i = 1; i <= m; i ++ )
            cout << res2[i] << " ";
    }
    
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_51879318/article/details/129250987