POJ 2970 The lazy programmer

很水的一道题 本来不值得写总结的 不过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
*/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值