很水的一道題 本來不值得寫總結的 不過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
*/