题解 P3619 魔法
题目传送>>P3619
题意简述:
- 拥有时间 T ,需完成 n 个任务,当 T>ti 即可完成此任务,完成后 T 加
b_i ,求是否能完成这 n 个任务。 - Z 个测试点。
题目分析:
根据题意,我们必须不断探索选择当下应该完成哪个任务致使最终能全部完成,这完全符合贪心算法,即局部最优导致产生全局最优解。判断贪心算法适用后,我们便需要选择贪心策略。根据题意,只有在 T>秒掉该题当然是幸事,但是我们在得到一个算法策略的时候并不应该直接敲代码,我们还要做什么呢?当然是验证算法策略是否正确,如果不正确那么你一来就敲的代码完全是竹篮打水一场空。
关于该题,我们对先前得到的优先选择
接下来我们推导正确的贪心策略,借助之前对旧策略的推翻过程,我们对其进行分析,如果我们先完成前一个任务致使 T 变小至达不到后二个任务的“门槛”,而先完成后一个任务,T 改变后我们依旧能达到前一个任务的“门槛”,此时:
推得:
即:
所以,我们只需依据
Code:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define endl '\n' //加速endl换行
struct task{ //利用结构体存ti,bi
int t,b;
} a[100001];
int cmp(task x,task y) //写cmp函数辅助sort排序
{
return x.t+x.b>y.t+y.b;
}
int main()
{
//freopen("input.in","r",stdin);
//freopen("print.out","w",stdout);
ios::sync_with_stdio(0); //加速cin输入和cout输出
int Z,n,T; //定义测试点数,任务数,拥有时间
bool flag; //定义flag标记任务推进进程
cin>>Z;
for (int i=1;i<=Z;i++)
{
cin>>n>>T;
for (int j=1;j<=n;j++)
{
cin>>a[j].t>>a[j].b;
}
sort(a+1,a+1+n,cmp); //排序
flag=1; //初始化flag
for (int j=1;j<=n;j++)
{
if (T>a[j].t&&T+a[j].b>0) //能够推进
{
T+=a[j].b; //T改变
}
else
{
cout<<"-1s"<<endl; //推进中断,直接输出不能完成,并换行
flag=0; //改变flag,标记为中断
break;
}
}
if (flag==1) //任务得以一路到底
{
cout<<"+1s"<<endl; //能输出够完成任务,并换行
}
}
return 0; //结束整个程序
}
结果(未吸氧):
企鹅的题解到此结束,祝各位 OIers 进步 ++~