hdu4884 模拟

besthacker2的第二题,模拟了22遍才模拟对,详细看代码吧,所有细节都已标出。

附代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;

int n,t,k,m;

struct node
{
    int st,et,p,v,mb;
} cc[1001];

int main()
{
    int T;
    cin>>T;
    while (T--)
    {
        scanf("%d%d%d%d",&n,&t,&k,&m);
        for (int i=1;i<=m;i++)
        {
            int a,b;
            int p,v;
            scanf("%d:%d%d%d",&a,&b,&p,&v);
            cc[i].st=a*60+b;
            cc[i].p=p;
            cc[i].v=v;
            cc[i].mb=0;
        }
        int cur=1;
        for (int i=cc[1].st;;i+=t) //i代表当前这次炒饭的起始时间
        {
            int p=cc[cur].p;
            int v=k;    //当前这次炒饭最多炒这么多
            if (v<cc[cur].v)
            {
                int d=(cc[cur].v-v)/k;    //如果当前这次炒最多也不够当前人的量,当前继续炒同一种,直至超过当前人的需要
                if ((cc[cur].v-v)%k!=0)
                    d++;
                v=v+(d)*k;
                i=i+(d)*t;
            }
            int j;
            int pp=0;
            for (j=cur;j<=m&&cc[j].st<=i;j++)   //从当前人开始向后查在开始炒之前所有需要这种炒饭的总份数,如果能满足则直接满足
            {
                if (cc[j].mb==1)    //如果已经满足过,直接跳过
                    continue ;
                if (cc[j].p==p&&cc[j].v<=v)     //当前的炒饭种类和分数满足当前这个人的需要
                {
                    v-=cc[j].v;     //满足他,然后看剩余部分是否够下个人的
                    cc[j].et=i+t;   //此人走的时间为当前这份炒饭炒完的时间
                    cc[j].mb=1;     //标记为已经满足
                    continue ;
                }
                if (pp==0) //如果当前的分数或者种类不满足,则下一个需要满足的人肯定是他(队首位置)
                {
                    cur=j;
                    pp=1;
                }
                if (cc[j].p==p)     //如果当前没有到末尾且炒饭种类一样,但是不能满足需求,那么肯定是份数不够,先满足部分
                    break;
            }
            if (j<=m&&cc[j].st<=i)  //先满足此人部分的情况
                cc[j].v-=v;
            if (pp==0)      //如果在开始这次炒饭时间之前的人的需求都满足了,则直接把下一个时刻来的人设为要满足的人
            {
                cur=j;
                if (cur>m)      //如果当前需要满足的人已经超过队列长度,则处理完毕
                    break;
                i=cc[cur].st-t>i?cc[cur].st-t:i;    //下一个开始炒饭时间为下一个人来的时间和这次炒饭完成时间的较大者,循环中+t
            }
        }
        for (int i=1;i<=m;i++)
        {
            int a=cc[i].et/60;
            a%=24;
            int b=(cc[i].et)%60;
            printf("%02d:%02d\n",a,b);
        }
        if (T)
            printf("\n");
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值