Codeforces Round #776 (Div. 3)
阿新 • • 發佈:2022-03-10
比賽連結:
https://codeforces.com/contest/1650
F. Vitaly and Advanced Useless Algorithms
題目大意:
有 \(n\) 個任務要完成,每個任務都有一個 \(deadline a_i\),即在第 \(a_i\) 小時及之前要完成該任務,剛開始每個任務的完成度都是 0%,當完成度達到 100% 或以上的時候該任務完成。
現在有 \(m\) 個計劃,第 \(i\) 個計劃有三個數 \(e_i\),\(t_i\),\(p_i\),表示如果選了這個計劃就會在當前時間開始的 \(t_i\) 小時後完成 \(p_i\)% 的任務 \(e_i\),這段時間不能做其它任務,且每一個任務只能進行一次。
時間從 0 開始,先要求找到一個執行計劃的順序來完成所有任務,若找不到輸出 -1。
思路:
我們可以先按照每個計劃完成的任務進行分類,這樣子就得到了能完成每個任務的所有計劃。
接下來就是找到一個執行計劃的方案,用最短的時間,讓這個計劃的完成度達到 100% 或以上,因為每個計劃只能執行一次,可以看出是一個 01揹包問題。
揹包容量為 100,即完成度,每個計劃看成一個物品,物品的價值是時間,重量是完成度,求最小的時間,做 01揹包,並求出具體方案。
程式碼:
#include <bits/stdc++.h> using namespace std; #define LL long long #define IOS() ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0); #define pb push_back const int INF = 1e9 + 10; struct node{ LL t, p, id; }; void solve(){ LL n, m; cin >> n >> m; vector <LL> a(n); vector <node> v[n + 1]; for (int i = 0; i < n; ++ i) cin >> a[i]; for (int i = 0; i < m; ++ i){ LL e, t, p; cin >> e >> t >> p; v[e].pb({t, p, i + 1}); } LL s = 0; vector <LL> ans; for (int i = 1; i <= n; ++ i){ vector <LL> dp(101, INF), pre[101]; dp[0] = 0; for (auto x : v[i]){ for (int j = 100; j >= 0; -- j){ if (dp[j] > dp[max(0LL, j - x.p)] + x.t){ dp[j] = dp[max(0LL, j - x.p)] + x.t; pre[j] = pre[max(0LL, j - x.p)]; pre[j].pb(x.id); } } } s += dp[100]; if (s > a[i - 1]){ cout << "-1\n"; return; } for (auto x : pre[100]) ans.pb(x); } cout << ans.size() << "\n"; for (int i = 0; i < ans.size(); ++ i) cout << ans[i] << " \n"[i == ans.size() - 1]; } int main(){ IOS(); LL T; cin >> T; while (T--) solve(); return 0; }