题解 CF1203 F1,F2 Complete the Projects

12.03 在我心目中一直是一个特别的数字呢 QwQ

比赛链接

CF1203F1 Complete the Projects (easy version)

题目链接

暴力做法,是直接枚举全排列。如果想要DP,则必须记录之前已经用过了哪些项目,复杂度势必大于(2^n)。故考虑挖掘题目的性质,尝试贪心。如果我们能贪心地求出一个最优(最有可能有解)的排列方式,则直接按照这种排列方式排好序后模拟一遍,就能判断答案是YES或NO了。

我们把项目,按照(b_igeq 0)(b_i<0)分为两类。显然,应该先完成所有(b_igeq 0)的项目。于是问题变为两类项目内部应该分别如何排序。

对于(b_igeq 0)的项目,把它们按(a_i)从小到大排序。这是因为,随着这类项目的进行,(r)的值单调不降,所以把一个(a_i)大的项目排在(a_i)小的项目前面是没有意义的(交换以后不会变劣)。

对于(b_i<0)的项目。首先,为了满足任何项目结束后(r)非负,我们令(a_i=max(a_i,-b_i))。于是接下来只需要考虑每个项目开始前(rgeq a_i)这个条件。

我们考虑两个项目((a_i,b_i))((a_j,b_j))(b_i,b_j<0)),在何种情况下,把(i)排在(j)前面更优。

  • 如果把(i)排在(j)前,则需要满足:(rgeq a_i), (r+b_igeq a_j) 。即:(rgeq max(a_i,a_j-b_i))
  • 如果把(j)排在(i)前,则需要满足:(rgeq a_j), (r+b_jgeq a_i) 。即:(rgeq max(a_j,a_i-b_j))

若要使把(i)排在(j)前面更优(更有可能有解),则:(max(a_i,a_j-b_i)leq max(a_j,a_i-b_j))

因为(b_i,b_j<0),所以(a_j-b_i>a_j)。所以后半部分的最大值一定不能取(a_j),即:(a_j<a_i-b_j (1))

同时,要使得(max(a_i,a_j-b_i)leq a_i-b_j),即:(a_ileq a_i-b_j (2)), (a_j-b_ileq a_i-b_j (3))

因为(b_j<0),所以((2))式恒成立。由((1),(3))得:(a_i+b_igeq a_j+b_j)

于是我们得出结论,把(i)排在(j)前面更优,当且仅当:(a_i+b_igeq a_j+b_j)。也就是说,对于所有(b_k<0)的二元组((a_k,b_k)),我们将它们按((a_k+b_k))的值从大到小排列即可。

时间复杂度(O(nlog n))

参考代码(片段):

const int MAXN=100;
int n,cur,cnt_po,cnt_ne;
struct node{
	int a,b;
}po[MAXN+5],ne[MAXN+5];
bool cmp_po(node x,node y){return x.a<y.a;}
bool cmp_ne(node x,node y){return x.a+x.b>y.a+y.b;}
int main() {
	read(n);read(cur);
	for(int i=1;i<=n;++i){
		int a,b;read(a);read(b);
		if(b<0){
			++cnt_ne;
			ne[cnt_ne].a=max(a,-b);
			ne[cnt_ne].b=b;
		}
		else{
			++cnt_po;
			po[cnt_po].a=a;
			po[cnt_po].b=b;
		}
	}
	sort(po+1,po+cnt_po+1,cmp_po);
	sort(ne+1,ne+cnt_ne+1,cmp_ne);
	for(int i=1;i<=cnt_po;++i){
		if(cur<po[i].a){puts("NO");return 0;}
		cur+=po[i].b;
	}
	for(int i=1;i<=cnt_ne;++i){
		if(cur<ne[i].a){puts("NO");return 0;}
		cur+=ne[i].b;
	}
	puts("YES");
	return 0;
}

CF1203F2 Complete the Projects (hard version)

题目链接

根据上一题中的分析,我们仍然可以把所有项目,按(b_igeq 0)(b_i<0)分为两类。且所有第一类项目排在所有第二类项目前面。

对于(b_igeq0)的项目,我们只需要把它们按(a_i)从小到大排序后,贪心地能选则选。因为选了当前项目,能使答案增加,且(r)不会减少。

对于(b_i<0)的项目,我们仍然把它们按照((a_i+b_i))从大到小排列。现在相当于从中选出一个子序列(不用改变选出的元素的顺序),使其合法。

考虑DP。设(dp[i][j])表示考虑了(排序后的)前(i)个((b_k<0)的)项目,完成第(i)个项目后,rating为(j),此条件下,最多做了多少个项目。转移分为不做当前项目,和做当前项目两种情况。即:

[dp[i][j]=max(dp[i-1][j],dp[i-1][j-b_i]+1) ]

时间复杂度(O(nlog n+nm))。其中(m)表示整个过程中的最大rating,(mleq r+nbleq 60000)

参考代码:

//problem:CF1203F2
#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define mk make_pair
#define lob lower_bound
#define upb upper_bound
#define fi first
#define se second
#define SZ(x) ((int)(x).size())

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;

namespace Fread{
const int MAXN=1<<20;
char buf[MAXN],*S,*T;
inline char getchar(){
	if(S==T){
		T=(S=buf)+fread(buf,1,MAXN,stdin);
		if(S==T)return EOF;
	}
	return *S++;
}
}//namespace Fread
#ifdef ONLINE_JUDGE
	#define getchar Fread::getchar
#endif
template<typename T>inline void read(T& x){
	x=0;int f=1;
	char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch))x=x*10+(ch-'0'),ch=getchar();
	x*=f;
}
/*  ------  by:duyi  ------  */ // myt天下第一
const int MAXN=100,MAXR=30000;
int n,cur,cnt_po,cnt_ne,ans,dp[MAXN+5][MAXR*2+5];
struct node{
	int a,b;
}po[MAXN+5],ne[MAXN+5];
bool cmp_po(node x,node y){return x.a<y.a;}
bool cmp_ne(node x,node y){return x.a+x.b>y.a+y.b;}
int main() {
	read(n);read(cur);
	for(int i=1;i<=n;++i){
		int a,b;read(a);read(b);
		if(b<0){
			++cnt_ne;
			ne[cnt_ne].a=max(a,-b);
			ne[cnt_ne].b=b;
		}
		else{
			++cnt_po;
			po[cnt_po].a=a;
			po[cnt_po].b=b;
		}
	}
	sort(po+1,po+cnt_po+1,cmp_po);
	sort(ne+1,ne+cnt_ne+1,cmp_ne);
	for(int i=1;i<=cnt_po;++i){
		if(cur<po[i].a)continue;
		cur+=po[i].b;ans++;
	}
	assert(cur<=MAXR*2);
	dp[0][cur]=ans;
	for(int i=1;i<=cnt_ne;++i){
		for(int j=0;j<=cur;++j){
			dp[i][j]=dp[i-1][j];
			if(j-ne[i].b<=cur&&j-ne[i].b>=ne[i].a){
				dp[i][j]=max(dp[i][j],dp[i-1][j-ne[i].b]+1);
			}
		}
	}
	for(int i=0;i<=cur;++i)ans=max(ans,dp[cnt_ne][i]);
	cout<<ans<<endl;
	return 0;
}
原文地址:https://www.cnblogs.com/dysyn1314/p/12659433.html