Codeforces 1203F (greedy, DP)

Meaning of the questions: There are n tasks, your initial rating is m, n tasks which have two indicators: the completion of the lowest rating (a [i]) required for this task, as well as rating changes after the completion of this task ( may be negative) (b [i]). rating can not be negative. F1: ask if there is a task to complete the order, before it may all tasks can be completed. F2: You can choose any number of tasks to complete, ask how many tasks can be completed up to.

Ideas:

F1: First task is divided into two parts: the rise and fall of the rating the rating. For rating up tasks, directly in accordance with a [i] can be ordered from small to large. why? Because the rating will not be smaller than the original rating after completion, formerly able to complete the task can certainly be completed after the completion of other tasks, if you can complete all, began to consider lowering the rating section. We consider a decline in rating section, we consider the rating after each task execution lower bound, and press circles in descending order, that is, the lower bound of preference large task, the higher the smaller the impact of the lower bound on the back.

Code:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 110;
struct node {
	int x, y;
};
vector<node> a, b;
bool cmp1(node t1, node t2) {
	return t1.x < t2.x;
}
bool cmp2(node t1, node t2) {
	return (max(t1.x, -t1.y) + t1.y) > (max(t2.x, -t2.y) + t2.y);
}
int main() {
	int n, m, cnt1 = 0, cnt2 = 0;
	scanf("%d%d", &n, &m);
	int sum = 0;
	node tmp;
	for (int i = 1; i <= n; i++) {
		scanf("%d%d", &tmp.x, &tmp.y);
		if(tmp.y >= 0) a.push_back(tmp);
		else b.push_back(tmp);
	}
	sort(a.begin(), a.End (), CMP1);
	sort(b.begin(), b.end(), cmp2);
	int ans = 0;
	for (int i = 0; i < a.size(); i++) {
		if(m < a[i].x) ans = -1;
		m += a[i].y;
	}
	for (int i = 0; i < b.size(); i++) {
		if(m < b[i].x) ans = -1;
		m += b[i].y;
	}
	if(ans == -1) printf("NO\n");
	else printf("YES\n");
} 

F2: This is obviously a backpack DP, DP directly but is O (n * n * m) of each task because the choice will affect the remaining tasks. DP this time out. By F1's conclusion that we simply enumerate the current task to select or not select on the line if we put part of the drop rating in accordance with the lower bound of the sort, select the upper bound of the high priority task, so we DP transfer, because such decisions are optimal, so do not need to consider the impact of the previous task is completed, so that O (n * m) of the DP process complexity can be completed.

Code:

#include <bits/stdc++.h>
#define pii pair<int, int>
using namespace std;
const int maxn = 600010;
int dp[110][maxn];
bool cmp(pii t1, pii t2) {
	return (t1.first + t1.second) > (t2.first + t2.second);
}
vector<pii> a, b;
int main() {
	int n, m;
	scanf("%d%d", &n, &m);
	pii tmp;
	for (int i = 1; i <= n; i++) {
		scanf("%d%d", &tmp.first, &tmp.second);
		if(tmp.second >= 0) a.push_back(tmp);
		else b.push_back(tmp);
	}
	sort(a.begin(), a.end());
	sort(b.begin(), b.end(), cmp);
	int mx = m, tot = 0;
	for (int i = 0; i < a.size(); i++) {
		 if(a[i].first <= mx) {
		 	mx += a[i].second;
		 	tot++;
		 }
	}
	int ans = 0;
	dp[0][mx] = tot;
	for (int i = 0; i < b.size(); i++) {
		for (int j = 0; j <= mx; j++) {
			if(j >= b[i].first && j + b[i].second >= 0) {
				dp[i + 1][j + b[i].second] = max(dp[i + 1][j + b[i].second], dp[i][j] + 1);
			}
			dp[i + 1][j] = max(dp[i + 1][j], dp[i][j]);
		}
	}
	for (int i = 0; i <= mx; i++) {
		ans = max(ans, dp[b.size()][i]);
	}
	printf("%d\n", ans);
} 

  

 

Guess you like

Origin www.cnblogs.com/pkgunboat/p/11361313.html