zoukankan      html  css  js  c++  java
  • pat甲级 1026

    参考题解

    条理清晰,十分优秀。

    除了别人都说过的坑点以外,还要注意:

    选服务窗口,不是找上次结束时间最小的,而应该是找下个顾客到来时第一个空闲下来的。

    测试用例:

    4

    08:00:00 30 1

    08:10:00 10 1

    08:25:00 10 1

    09:00:00 10 1

    3 1

    2

    应输出:

    08:00:00 08:00:00 0

    08:10:00 08:10:00 0

    08:25:00 08:25:00 0

    09:00:00 09:00:00 0

    2 2 0 

    29分代码

    #include <bits/stdc++.h>
    #define ll long long
    
    using namespace std;
    int N, K, M;
    int T[110], cnt[110];
    vector<int> ans[110];
    char vis[110];
    struct node
    {
        int a, s, p, d, v;
    }pr[10010];
    
    int main()
    {
        int hh, mm, ss, p;
        scanf("%d", &N);
        for (int i = 0; i < N; i++) {
            scanf("%d:%d:%d %d %d", &hh, &mm, &ss, &pr[i].p, &pr[i].v);
            pr[i].a = (hh*60+mm)*60+ss, pr[i].s = -1, pr[i].p = min(pr[i].p, 120);
        }
        sort(pr, pr+N, [](node u, node v) { return u.a < v.a; });
        scanf("%d %d", &K, &M);
        for (int i = 0; i < M; i++) {
            scanf("%d", &p);
            vis[p] = 1;
        }
        for (int i = 1; i <= K; i++) T[i] = 8*60*60;
        for (int i = 0; i < N; i++) {
            if (pr[i].s != -1) continue;
            int minn = 22*60*60;
            vector<int> pos;
            for (int j = 1; j <= K; j++)
                if (minn > T[j]) {
                    minn = T[j];
                    pos.clear();
                    pos.push_back(j);
                } else if (minn == T[j]) {
                    pos.push_back(j);
                }
            int num = 0;
            while (num < (int)pos.size() && vis[pos[num]] == 0) num++;
            if (pr[i].a <= minn) {
                for (int j = i; j < N && pr[j].a < T[pos[num]] && num <(int)pos.size(); j++) {
                    // printf("%d %d %d %d
    ", j, pr[j].a, minn, pr[j].v);
                    if (pr[j].v) {
                        pr[j].s = max(pr[j].a, T[pos[num]]);
                        if (pr[j].s < 21*60*60) {
                            T[pos[num]] = pr[j].s + pr[j].p*60;
                            cnt[pos[num]]++;
                            ans[pos[num]].push_back(j);
                            do {
                                num++;
                            } while(num < (int)pos.size() && vis[pos[num]] == 0);
                        }
                    }
                }
            }
            if (pr[i].s == -1) {
                minn = 22*60*60;
                int p[2] = {-1, -1}, now;
                for(int j = 1; j <= K; j++) {
                    if(T[j] <= pr[i].a && p[0] == -1) {
                        p[0] = j;
                        break;
                    } else if(minn > T[j]) {
                        minn = T[j];
                        p[0] = j;
                    }
                }
                if(pr[i].v) {
                    for(int j = 1; j <= K; j++)
                        if(T[j] <= pr[i].a && vis[j]) {
                            p[1] = j;
                            break;
                        }
                    if(p[1] != -1) now = p[1];
                    else now = p[0];
                } else now = p[0];
                pr[i].s = max(pr[i].a, T[now]);
                if(pr[i].s < 21*60*60) {
                    T[now] = pr[i].s + pr[i].p*60;
                    cnt[now]++;
                    ans[now].push_back(i);
                }
            }
        }
        sort(pr, pr+N, [](node u, node v){ return u.s < v.s; });
        for (int i = 0; i < N; i++) {
            if (pr[i].s == -1 || pr[i].s >= 21*60*60) continue;
            printf("%02d:%02d:%02d %02d:%02d:%02d %d
    ",
                pr[i].a/60/60, (pr[i].a/60)%60, pr[i].a%60,
                pr[i].s/60/60, (pr[i].s/60)%60, pr[i].s%60, (pr[i].s-pr[i].a+30)/60 );
        }
        for (int i = 1; i <= K; i++) {
            printf("%d", cnt[i]);
            if (i != K) printf(" ");
            else printf("
    ");
        }
        /*for (int i = 1; i <= K; i++) {
            for (int j = 0; j < (int)ans[i].size(); j++)
                printf("%d ", ans[i][j]);
            puts("~");
        }*/
        return 0;
    }
    
    /*
    
    9
    20:52:00 10 0
    08:00:00 20 0
    08:02:00 30 0
    20:51:00 10 0
    08:10:00 5 0
    08:12:00 10 1
    20:50:00 10 0
    08:01:30 15 1
    20:53:00 10 1
    3 1
    2
    
    08:00:00 08:00:00 0
    08:01:30 08:01:30 0
    08:02:00 08:02:00 0
    08:12:00 08:16:30 5
    08:10:00 08:20:00 10
    20:50:00 20:50:00 0
    20:51:00 20:51:00 0
    20:52:00 20:52:00 0
    3 3 2
    
    3
    08:00:00 10 0
    08:05:00 5 0
    08:08:00 10 1
    2 1
    2
    
    4
    08:00:00 30 1
    08:10:00 10 1
    08:25:00 10 1
    09:00:00 10 1
    3 1
    2
    
    */
    View Code

    我很多时候做这种处理事务的模拟题,喜欢提前处理后面的事务。但是这样很容易出错,可能有很多情况没有考虑到。

    比如我这种方法,如果在处理队列里的VIP用户时,不一定是分配了最小的VIP桌子,而是分配了结束时间最早的桌子;而如果改成分配最小的VIP桌子,当队列里有多个VIP用户时,需要重新遍历一次,时间复杂度太高。

    不如参考的代码一次只处理一个用户,时间复杂度相同,且不会遗漏情况。

    不是需要最巧妙的,而是需要最简单的、最清晰的。

    备份一下参考代码

      1     #include<iostream>
      2     #include<vector>
      3     #include<set>
      4     #include<algorithm>
      5     using namespace std; 
      6     const int OPEN = 3600 * 8;
      7     const int CLOSE = 3600 * 21;
      8     struct cus{
      9         int arvT, serT = -1, costT, flag; 
     10     };  
     11     vector<cus> Vu; //顾客
     12     int FreeT[101]; //桌子空闲的时间
     13     set<int> VipT;//vip桌子
     14     int SerCnt[101];//每个桌子服务的人数
     15     int N, K, M; 
     16     bool cmp(cus A, cus B) {return A.arvT < B.arvT;} 
     17     bool cmp2(cus A, cus B) {return A.serT < B.serT;} 
     18     int selectT(int arvT){
     19         int ret, min = 123123123;
     20         for (int i = 1; i <= K; i++){
     21             if (arvT >= FreeT[i]){
     22                 ret = i;
     23                 break;
     24             }
     25             else if (FreeT[i] < min){
     26                 min = FreeT[i];
     27                 ret = i;
     28             }
     29         }
     30         return ret;
     31     }  
     32     int VipInQue(int s, int time){
     33         int ret = -1;
     34         for (int i = s; i < Vu.size(); i++){
     35             if (Vu[i].flag == 1 && Vu[i].serT == -1 && Vu[i].arvT < time){
     36                 ret = i;
     37                 break;
     38             }
     39         }
     40         return ret;
     41     } 
     42     int vipTable(int arvT){
     43         int ret = -1;
     44         for (auto it = VipT.begin(); it != VipT.end(); it++) {
     45             if (FreeT[*it] <= arvT) {
     46                 ret = *it;
     47                 break;
     48             }
     49         } 
     50         return ret;
     51     } 
     52     int main(){
     53         scanf("%d", &N);
     54         int x;
     55         for (int i = 0; i < N; i++){
     56             int h, m, s;
     57             cus tmp;
     58             scanf("%d:%d:%d %d %d", &h, &m, &s, &tmp.costT, &tmp.flag);
     59             tmp.arvT = 3600 * h + 60 * m + s; 
     60             if (tmp.costT > 120)
     61                 tmp.costT = 120;
     62             tmp.costT *= 60;
     63             Vu.push_back(tmp);
     64         }
     65         scanf("%d%d", &K, &M); 
     66         for (int i = 0; i < M; i++) {
     67             scanf("%d", &x);
     68             VipT.insert(x);
     69         }  
     70         fill(FreeT, FreeT + 101, OPEN);
     71         sort(Vu.begin(), Vu.end(), cmp);
     72         for (int i = 0; i < Vu.size();){
     73             if (Vu[i].serT != -1){//如果该顾客已经安排过,安排下一位
     74                 i++;
     75                 continue;
     76             } 
     77             int t = selectT(Vu[i].arvT);
     78             if (VipT.find(t)!= VipT.end() && Vu[i].flag == 0 && VipInQue(i + 1, FreeT[t]) != -1){
     79                 //选中的空闲桌是vip桌,队首不是vip,并且队列里有排队的vip
     80                 x = VipInQue(i + 1, FreeT[t]);//将这个空闲vip桌分配给队列中第一个vip
     81                 Vu[x].serT = FreeT[t];
     82                 FreeT[t] = Vu[x].serT + Vu[x].costT;
     83                 if (Vu[x].serT < CLOSE)
     84                     SerCnt[t]++;
     85             }
     86             else if (VipT.find(t) == VipT.end() && Vu[i].flag == 1 && vipTable(Vu[i].arvT) != -1) {
     87                 //选中的桌子不是vip桌子,但是队首是vip,且有空闲的vip桌子
     88                 x = vipTable(Vu[i].arvT); //找一个vip桌分配给队首
     89                 Vu[i].serT = Vu[i].arvT;
     90                 FreeT[x] = Vu[i].serT + Vu[i].costT;
     91                 if (Vu[i].serT < CLOSE)
     92                     SerCnt[x]++;
     93                 i++;
     94             }
     95             else{
     96                 if (Vu[i].arvT >= FreeT[t]) 
     97                     Vu[i].serT = Vu[i].arvT; 
     98                 else
     99                     Vu[i].serT = FreeT[t]; 
    100                 FreeT[t] = Vu[i].serT + Vu[i].costT; 
    101                 if (Vu[i].serT < CLOSE)
    102                     SerCnt[t]++;
    103                 i++;
    104             }
    105         } 
    106         sort(Vu.begin(), Vu.end(), cmp2);
    107         for (int i = 0; i < Vu.size(); i++){
    108             if (Vu[i].serT < CLOSE)
    109                 printf("%02d:%02d:%02d %02d:%02d:%02d %d
    ", Vu[i].arvT / 3600, (Vu[i].arvT % 3600) / 60, Vu[i].arvT % 60,
    110                     Vu[i].serT / 3600, (Vu[i].serT % 3600) / 60, Vu[i].serT % 60, (Vu[i].serT - Vu[i].arvT + 30) / 60);
    111         } 
    112         for (int i = 1; i <= K; i++){
    113             if (i != 1)
    114                 printf(" ");
    115             printf("%d", SerCnt[i]);
    116         } 
    117         return 0;
    118     }
    View Code
  • 相关阅读:
    canvas背景粒子动态变化动画
    点击屏幕弹出心形效果
    前端图片的性能优化
    vue的computed和method的区别
    es6的...
    命名路由和命名视图
    编程式路由
    [思维]蚂蚁感冒
    [模板]前缀树 / 字典树及应用
    [模板]三分搜索
  • 原文地址:https://www.cnblogs.com/canchan/p/12967211.html
Copyright © 2011-2022 走看看