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;
}
此生无悔入OI 来生AK IOI

浙公网安备 33010602011771号