CF1650F Vitaly and Advanced Useless Algorithms

CF1650F

原题链接 ←Click it

题目大意:有\(n\)个课程,每个课程的截止时间是\(a_i(a_i < a_i < a_2 <...< a_n)\),要求在在规定时间内完成课程。现在有\(m\)个方案,每个方案表示对第\(i\)个课程学习\(t\)时间,增加完成度\(p\),要求方案能重复选择。如可以完成,则输出方案的个数,以及选择的方案,要求时间最短;如不能按时完成,则输出\(-1\)

解题思路:考虑每个课程都是一个小的背包问题,对每个课程分开求解,如果可以完成,则利用dp数组反推出是由哪些方案转移过来的。

参考代码:

void solve() {
    int n, m;
    cin >> n >> m;
    vector<int> a(n);
    vector<int> res;
    for(int i = 0; i < n; i ++) {
        cin >> a[i];
    }
    struct node {
        int t, p, idx;
    };
    vector<vector<node>> op(n);
    for(int i = 0; i < m; i ++) {
        int e, p, t;
        cin >> e >> t >> p;
        e --;
        op[e].push_back({t, p, i + 1});
    }
    int tm = 0;
    for(int i = 0; i < n; i ++) {
        int N = op[i].size();
        vector<vector<int>> dp(N + 1, vector<int> (101, 1e9 + 1));
        dp[0][0] = 0;
        for(int j = 0; j < N; j ++) {
            dp[j + 1] = dp[j];
            for(int k = 0; k <= 100; k ++) {
                int ed = min(100, k + op[i][j].p);
                dp[j + 1][ed] = min(dp[j + 1][ed], dp[j][k] + op[i][j].t);
            }
        }
        tm += dp[N][100];
        if(tm > a[i]) {
            cout << "-1\n";
            return ;
        }
        int now = 100;
        for(int j = N -1 ; j >= 0; j --) {
            if(dp[j + 1][now] == dp[j][now]) {
                continue;
            }
            res.push_back(op[i][j].idx);
            for(int f = 0; f <= now; f ++) {
                int t = min(100, f + op[i][j].p);
                if(now == t && dp[j][f] + op[i][j].t == dp[j + 1][t]) {
                    now = f;
                    break;
                }
            }
        }
    }
    cout << res.size() << '\n';
    for(auto x : res) {
        cout << x << ' ';
    }
    cout << '\n';
}
posted @ 2022-03-23 20:00  Muly  阅读(60)  评论(0)    收藏  举报