P3619

魔法

题目描述

cjwssb 知道是误会之后,跟你道了歉。你为了逗笑他,准备和他一起开始魔法。不过你的时间不多了,但是更惨的是你还需要完成 \(n\) 个魔法任务。假设你当前的时间为 \(T\),每个任务需要有一定的限制 \(t_i\) 表示只有当你的 \(T\) 严格大于 \(t_i\) 时你才能完成这个任务,完成任务并不需要消耗时间。当你完成第 \(i\) 个任务时,你的时间 \(T\) 会加上 \(b_i\),此时要保证 \(T\) 在任何时刻都大于 \(0\),那么请问你是否能完成这 \(n\) 个魔法任务,如果可以,输出 \(\texttt{+1}\texttt{s}\),如果不行,输出 \(\texttt{-1}\texttt{s}\)

输入格式

第一行:一个整数 \(Z\),表示有 \(Z\) 个测试点。

对于每个测试点:

第一行:两个整数 \(n,T\),表示有 \(n\) 个任务,你一开始有 \(T\) 的时间。

接下来 \(n\) 行,每行 \(2\) 个数字,\(t_i\)\(b_i\)

输出格式

对于每个测试点,输出 \(\texttt{+1}\texttt{s}\) 或者 \(\texttt{-1}\texttt{s}\)

样例 #1

样例输入 #1

1
2 13
1 -9
5 -3

样例输出 #1

+1s

提示

对于 \(20\%\) 的数据,\(n\leq10\)

对于 \(100\%\) 的数据,\(n\leq10^5,Z\leq10,t_i\leq10^5,T\leq10^5,-10^5\leq b_i\leq 10^5\)


先说我最开始凭感觉的排序方法:

bool cmp(did x,did y)
{
	if(x.t==y.t)return x.b>y.b;
	if(abs(x.b-x.t)!=abs(y.b-y.t))return abs(x.b-x.t)<abs(y.b-y.t);
	return x.t<y.t;
}
这样的方法已经可以骗91Pts了(主要就是想先考虑b对T的影响 再考虑t)

正解:这题的正解贪心分析方法值得学习
考虑i j 假设若按 i j 的顺序则只能完成i 不能完成j
而按照 j i 的顺序都能完成 那么就能分析出最优的情况
i j : T+a[i].b<=a[j].t
j i : T+a[j].b>a[i].t
->:a[i].t-a[j].b<T<=a[j].t-a[i].b
即有:a[i].t+a[i].b<a[j].t+a[j].b
所以按照 t+b 降序排序即可
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int z,n,T;
struct did{
	int t,b;
}a[100005];
bool cmp(did x,did y)
{
	if(x.t==y.t)return x.b>y.b;
	if(abs(x.b-x.t)!=abs(y.b-y.t))return abs(x.b-x.t)<abs(y.b-y.t);
	return x.t<y.t;
}
bool cmpp(did x,did y)
{
	return x.t+x.b>y.t+y.b;
}
signed main()
{
	ios::sync_with_stdio(false);
	cin>>z;
	while(z--)
	{
		cin>>n>>T;
		for(int i=1;i<=n;i++)
			cin>>a[i].t>>a[i].b;
		sort(a+1,a+n+1,cmpp);
		int flag=1;
		for(int i=1;i<=n;i++)
		{
			if(T>a[i].t)T+=a[i].b;
			else
			{
				flag=0;
				break;
			}
			if(T<=0)
			{
				flag=0;
				break;
			}
		}
		if(flag)cout<<"+1s\n";
		else cout<<"-1s\n";
	}
	return 0;
} 
posted @ 2023-01-05 21:56  PKU_IMCOMING  阅读(15)  评论(0)    收藏  举报