很水的一道题 本来不值得写总结的 不过WA了很多次 还是记录一下当时犯的错误吧
首先讲讲思路:将n个项目排序 排序的规则是d小的优先 如果d相同 则a大的优先 同时设置一个初始值为0的变量time来表示时间的流逝 然后遍历每项目 如果当前的时间比我当前项目的deadline要晚 那么我就要从这个项目以及之前的项目来给钱“挤”时间出来 那么怎么选择从哪些项目来挤时间呢 很简单 选a大的来挤时间 可是遍历的时候a最大的项目应该是可以实时更新的 所以这个时候就要使用一个优先队列 这个队列定义a大的排在队列的前面 每次遍历一个项目时 都要将改项目添加到队列中 注意要实时更新队列中成员的b值 因为如果你一直在“挤”一个项目的时间 他终会变成瞬间完成
一开始做的时候蜜汁自信 连time的设置都能搞错 回来纠正过后还是WA 仔细检查代码才发现每次改变队列成员的b值时都忘记自己改变的只是一个临时设的变量 所以每次改变队列中的成员的b值时还要把更改后的成员重新插入队列
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <bitset>
#include <vector>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
const int maxn=100005;
int n;
long long time;
double cost;
struct web
{
int a;
int b;
int d;
bool operator < (const web k)const
{
if(a<k.a) return true;
if(a==k.a)
{
if(b<k.b)
{
return true;
}
}
return false;
}
}w[maxn];
priority_queue<web>q;
bool cmp(web x,web y)
{
if(x.d<y.d) return true;
if(x.d==y.d)
{
if(x.a>y.a)
{
return true;
}
}
return false;
}
void ini()
{
cost=0;time=0;
if(w[1].b>w[1].d)
{
cost+=(w[1].b-w[1].d)/(w[1].a*1.0);
w[1].b=w[1].d;
time=w[1].d;
q.push(w[1]);
}
else
{
time=w[1].b;
q.push(w[1]);
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&w[i].a,&w[i].b,&w[i].d);
}
sort(w+1,w+1+n,cmp);
ini();
for(int i=2;i<=n;i++)
{
q.push(w[i]);
long long total=time+w[i].b-w[i].d;
if(total<=0)
{
time=time+w[i].b;
}
else if(total>0)
{
while(total>0)
{
web v=q.top();
if(v.b>total)
{
cost+=(total)/(v.a*1.0);
v.b=v.b-total;
total-=total;
web tmp=v;q.pop();q.push(tmp);
}
else if(v.b<=total)
{
cost+=(v.b)/(v.a*1.0);
total-=v.b;
v.b-=v.b;
q.pop();
}
}
time=w[i].d;
}
}
printf("%.2f\n",cost);
}
/*
4
10 10 10
30 20 10
10 90 50
20 10 100
2
20 50 100
10 100 50
2
10 10 10
30 20 10
4
10 10 10
20 20 20
30 30 30
40 40 40
4
21 21 15
23 48 34
12 15 54
23 78 96
4
23 21 21
897 87 56
12 2 23
21 32 123
3
400 100 50
300 100 50
200 100 50
*/