数据结构——银行排队问题之单队列多窗口加VIP服务

版权声明:转载请注明 https://blog.csdn.net/NCC__dapeng/article/details/83112192

题目大意:有很多个服务窗口,有一个窗口是VIP窗口,如果这个窗口有空闲,并且排队等待的人里有VIP,那么VIP先去这个窗口办理业务(SORRY,充钱就是了不起),如果果有多个窗口可以选择,顾客会优先选择窗口编号小的。

题目链接:https://pintia.cn/problem-sets/1042354461223579648/problems/1042355242509160453#p-6

在网上看到很多博客评论这道题很恶心,在这里也跟风一下,这道题确实很恶心。 改了很多次思路,最终AC。

这道题,推荐自己疯狂尝试后,在看看题解是如何给出的,这道题会帮助你踩出很多的思维漏洞,额。。。说到思维漏洞,还有题意,注意题目中所给的窗口的编号是从0开始的(心粗的一批)。

现在这里说一下错思路的最终版本:

在这道题之前有一个单队列多窗口问题如果不知道,点这里,保持那个问题的整体框架不变,对VIP窗口进行特别的判断,当一个用户的选择是VIP窗口时,这时候就需要判断,队列中是否含有VIP会员,如果有的话,去找次的最快窗口,然后输出。

代码实现:

#include <bits/stdc++.h>

using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=1000+10;

struct node
{
    int st;
    int work;
    int vip;
    bool operator < (const node&s ) const
    {
        return st<s.st||(st==s.st&&vip>s.vip);
    }
};

struct nodes
{
    int num;
    int endtime;
    nodes() {num=0; endtime=0;}
};

node que[maxn];
nodes w[maxn];
bool used[maxn];

int main()
{
    int n; scanf("%d",&n);

    for(int i=0;i<n;i++)
    {
        scanf("%d %d %d",&que[i].st,&que[i].work,&que[i].vip);
        que[i].work = que[i].work>=60 ? 60: que[i].work;
    }
    sort(que,que+n);

//    for(int i=0;i<n;i++)
//    {
//        cout<<"输出中间值   "<<que[i].st<<"     "<<que[i].work<<"     "<<que[i].vip<<endl;
//    }
    int k,vipw; scanf("%d %d",&k,&vipw);
    vipw++;


    int max_w=0,max_f=0,sumw=0;

    //cout<<"检测"<<endl;
    for(int i=0; i<n; i++)
    {
        if(used[i]) continue;

        bool flag=false;

        int fw=INF,fn=INF;

        for(int j=1; j<=k; j++)
        {
            if(w[j].endtime<=que[i].st)
            {
                used[i]=true;

                w[j].num++;

                w[j].endtime=que[i].st+que[i].work;

                flag=true;

                //cout<<"输出最后窗口    "<<fn<<"   "<<i<<endl;
                break;
            }

            if(fw>(w[j].endtime-que[i].st))
            {
                fw=w[j].endtime-que[i].st;
                fn=j;
            }

        }

       // cout<<"输出过程值           "<<i<<"   "<<fn<<"    "<<flag<<endl;

        if(flag) continue;

        if(fn==1&&que[i].vip==0)
        {

            bool judge=false;
            int pos=0;

            for(int j=i+1;j<n;j++)
            {
                if(i+1<n&&que[j].vip==1&&que[j].st<=w[fn].endtime)
                {
                    judge=true;
                    pos=j;
                    //cout<<"输出搜索位置的值    "<<j<<endl;
                    break;
                }
            }

            if(judge)
            {

                int fw1=INF,fn1=INF;
                for(int j=1; j<=k; j++)
                {
                    if(j==fn) continue;
                    if(fw1>w[j].endtime-que[i].st)
                    {
                        fw1=w[j].endtime-que[i].st;
                        fn1=j;
                    }

                }

                used[pos]=true;
                used[i]=true;

                w[fn].num++;
                w[fn1].num++;

                max_w=max(max_w,w[fn].endtime-que[pos].st);
                max_w=max(max_w,w[fn1].endtime-que[i].st);

                sumw+=(w[fn].endtime-que[pos].st+w[fn1].endtime-que[i].st);

                w[fn].endtime=w[fn].endtime+que[pos].work;
                w[fn1].endtime=w[fn1].endtime+que[i].work;

                //cout<<"gg2      "<<max_w<<endl;

                 //cout<<"输出最后窗口    "<<fn<<"   "<<i<<endl;

            }
            else
            {
                used[i]=true;

                w[fn].num++;

                max_w=max(max_w,w[fn].endtime-que[i].st);

                sumw+=(w[fn].endtime-que[i].st);

                w[fn].endtime=w[fn].endtime+que[i].work;

                //cout<<"gg2      "<<max_w<<endl;
                //cout<<"输出最后窗口    "<<fn<<"   "<<i<<endl;


            }
        }
        else
        {
            used[i]=true;

            max_w=max(max_w,w[fn].endtime-que[i].st);

            w[fn].num++;

            sumw+=(w[fn].endtime-que[i].st);

            w[fn].endtime=w[fn].endtime+que[i].work;

            //cout<<"gg2      "<<max_w<<endl;
            //cout<<"输出最后窗口    "<<fn<<"   "<<i<<endl;


        }


    }

    for(int i=1;i<=k;i++)
        max_f=max(max_f,w[i].endtime);


    //cout<<"输出总的等待时间   "<<sumw<<endl;

    printf("%.1f %d %d\n",sumw*1.0/n,max_w,max_f);


    int isfirst=1;
    for(int i=1;i<k;i++)
    {
        if(!isfirst) printf(" ");
        if(i==vipw)
        {
             printf("%d %d",w[1].num,w[i+1].num);
        }
        else printf("%d",w[i+1].num);

        isfirst=false;
    }


    return 0;
}

但是提交玩成后只能获得25分,然后就开始寻找自己的错误,最后花了两个小时,才滤出了自己的漏洞,这应该也是这道题最恶心的地方。

当一个普通用户选择VIP窗口时,我们执行的操作是让她去寻找另一个次快的窗口,但是这里有个问题,就是那个插队的VIP办理业务非常快,你仍然要在那个VIP窗口排队,然后需要再一次的判断队列中是否有VIP,如果下一个VIP办理业务依旧很快,你仍然在VIP窗口排队,你需要再次考虑。。。。。。如此的循环下去,(PS:这个是一个简单的For循环能够解决,可以自己动手试一试)

然后就是正确的思路,暴力枚举时间流逝一i秒一秒的判断,因为最多有1000个人,而且没人办理业务的时间最多是60S,所以总时间最多就是60000,时间复杂度很小。

下面给出AC代码:

#include <bits/stdc++.h>

using namespace std;
const int maxn=2000;
const int INF=0x3f3f3f3f;



struct node
{
    int st,et,vip;
};



node que[maxn];
int wd[maxn];
bool used[maxn],te[11][maxn*60];

int main()
{
    int n;  scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d %d %d",&que[i].st,&que[i].et,&que[i].vip);
        que[i].et= que[i].et>=60 ? 60 : que[i].et;
    }

    int k,vipw; scanf("%d %d",&k,&vipw);

    int cnt=n,sumw=0,max_w=0,max_f=0;
    for(int t=0;cnt;t++)
    {

        if(te[vipw][t]==false)
        {

            for(int i=0;i<n;i++)
            {
                if(used[i]||!que[i].vip) continue;
                if(que[i].st>t) break;

                wd[vipw]++;

                max_w=max(max_w,t-que[i].st);

                max_f=max(max_f,t+que[i].et);

                sumw+=(t-que[i].st);

                cnt--;

                used[i]=true;


                for(int j=0;j<que[i].et;j++) te[vipw][t+j]=true;


                break;
            }
        }

        for(int i=0;i<k;i++)
        {
            if(te[i][t]==false)
            {
                for(int j=0;j<n;j++)
                {
                    if(used[j]) continue;
                    if(que[j].st>t) break;

                    wd[i]++;

                    max_w=max(max_w,t-que[j].st);

                    sumw+=(t-que[j].st);

                    cnt--;

                    used[j]=true;

                     max_f=max(max_f,t+que[j].et);

                    for(int h=0;h<que[j].et;h++) te[i][t+h]=true;

                    break;
                }
            }
        }
    }

    printf("%.1f %d %d\n",sumw*1.0/n,max_w,max_f);

    for(int i=0;i<k;i++)
    {
        if(i) printf(" ");
        printf("%d",wd[i]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/NCC__dapeng/article/details/83112192
今日推荐