1. 程式人生 > 其它 >Codeforces Round #776 (Div. 3)

Codeforces Round #776 (Div. 3)

比賽連結:

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;
}