zoukankan      html  css  js  c++  java
  • 2020.11.28 2020团体程序设计天梯赛补题报告

    L2-2 口罩发放 (25分)

     1.题意

      某市出于给市民发放口罩的需要,推出了一款小程序让市民填写信息,方便工作的开展。小程序收集了各种信息,包括市民的姓名、身份证、身体情况、提交时间等,但因为数据量太大,需要根据一定规则进行筛选和处理,请你编写程序,按照给定规则输出口罩的寄送名单。输入格式:输入第一行是两个正整数 D 和 P,表示有 D 天的数据,市民两次获得口罩的时间至少需要间隔 P 天。接下来 D 块数据,每块给出一天的申请信息。第 i 块数据的第一行是两个整数Ti,Si,表示在第 i 天有Ti条申请,总共有Si个口罩发放名额。随后Ti行,每行给出一条申请信息,格式如下:

      姓名 身份证号 身体情况 提交时间
    给定数据约束如下:
      姓名 是一个长度不超过 10 的不包含空格的非空字符串;
      身份证号 是一个长度不超过 20 的非空字符串;
      身体情况 是 0 或者 1,0 表示自觉良好,1 表示有相关症状;
      提交时间 是 hh:mm,为24小时时间(由 00:00 到 23:59。例如 09:08。)。注意,给定的记录的提交时间不一定有序;
      身份证号 各不相同,同一个身份证号被认为是同一个人,数据保证同一个身份证号姓名是相同的。
    能发放口罩的记录要求如下:
      身份证号 必须是 18 位的数字(可以包含前导0);
      同一个身份证号若在第 i 天申请成功,则接下来的 P 天不能再次申请。也就是说,若第 i 天申请成功,则等到第 i+P+1 天才能再次申请;
      在上面两条都符合的情况下,按照提交时间的先后顺序发放,直至全部记录处理完毕或 S​i个名额用完。如果提交时间相同,则按照在列表中出现的先后顺序决定。
    输出格式:
    对于每一天的申请记录,每行输出一位得到口罩的人的姓名及身份证号,用一个空格隔开。顺序按照发放顺序确定。在输出完发放记录后,你还需要输出有合法记录的、身体状况为 1 的申请人的姓名及身份证号,用空格隔开。顺序按照申请记录中出现的顺序确定,同一个人只需要输出一次。

     2.题解

      结构体存市民的信息,一个全局vector存有症状的市民,一个局部vector存每一天的市民信息,根据题意筛选排序后发放口罩,并记录有症状的市民。

     3.代码

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long;
     4 const int maxn = 1000 + 5;
     5 const int INF = 0x7FFFFFFF;
     6 struct mmp {
     7     string name;
     8     string idcard;
     9     int shen;
    10     int times;
    11     int index;
    12 };
    13 map<string, int> mp;
    14 set<string> smp;
    15 set<string> vHave;
    16 vector<mmp> v;
    17 bool cmp(mmp a, mmp b) {
    18     if(a.times == b.times) {
    19         return a.index < b.index;
    20     }
    21     return a.times < b.times;
    22 }
    23 int main() {
    24     int D, P;
    25     scanf("%d %d", &D, &P);
    26     for(int day = 1; day <= D; day++) {
    27         int ti, si;
    28         cin >> ti >> si;
    29         vector<mmp> use;
    30         for(int i = 1; i <= ti; i++) {
    31             string name;
    32             string idcard;
    33             int shen;
    34             int hh;
    35             int mm;
    36             cin >> name;
    37             cin >> idcard;
    38             cin >> shen;
    39             scanf("%d:%d", &hh, &mm);
    40             bool flag = true;
    41             if(idcard.length() != 18) {
    42                 continue;
    43             } 
    44             for(int j = 0; j < idcard.size(); j++) {
    45                 if (!(idcard[j] >= '0' && idcard[j] <= '9')) {
    46                     flag = false;
    47                 } 
    48             }  
    49             if(flag) {
    50                 if(shen && vHave.find(idcard) == vHave.end()) {
    51                     v.push_back(mmp{name, idcard, shen, hh * 60 + mm, i});
    52                     vHave.insert(idcard);
    53                 }
    54                 use.push_back(mmp{name, idcard, shen, hh * 60 + mm, i});
    55             }
    56         }
    57         sort(use.begin(), use.end(), cmp);
    58         int now = 0;
    59         for(int i = 0; i < use.size() && now < si; i++) {
    60             if(mp[use[i].idcard] == 0 || day >= P + mp[use[i].idcard] + 1) {
    61                 now++;
    62                 mp[use[i].idcard] = day;
    63                 cout << use[i].name << " " << use[i].idcard << endl;
    64             }
    65         }
    66     }
    67     for(int i = 0; i < v.size(); i++) {
    68         cout << v[i].name << " " << v[i].idcard << endl;
    69     }
    70         
    71     return 0;
    72 }
    View Code

     

    L2-3 完全二叉树的层序遍历 (25分)

     1.题意

      给出一棵完全二叉树的后序遍历,输出对应层序遍历。

     2.题解

      因为是后序遍历序列,所以最后一个元素是树的根节点,可以使用递归建树。若当前结点的右子树不为空则继续将右子树遍历,若右子树为空则判断当前结点是否存在右儿子,右儿子的编号为 this.num*2+1,如果右儿子的编号小于等于结点的数量n则表示存在右儿子,在此新建结点;若右子树不满足条件则考虑左子树,同样是假如当前结点的左子树不为空则继续向左子树遍历,否则判断当前结点是否存在左儿子,左儿子的编号为 this.num*2,如果左儿子的编号小于等于结点的数量n则表示存在左儿子,在此新建结点。最后使用队列实现层序遍历。

     3.代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n;
     4 int a[35];
     5 struct node {
     6     int value;
     7     int level;
     8     node* l;
     9     node* r;
    10     node(int value) {
    11         this->value = value;
    12         this->l = NULL;
    13         this->r = NULL;
    14         this->level = 1;
    15     }
    16 };
    17 bool flag;
    18 void build(node* root, int a, int num) {
    19     if(flag) {
    20         return ;
    21     }
    22     if(root->r) {
    23         build(root->r, a, num * 2 + 1);
    24     } else if(num * 2 + 1 <= n) {
    25         flag = true;
    26         root->r = new node(a);
    27         return;
    28     }
    29     if(flag) {
    30         return ;
    31     }
    32     if(root->l) {
    33         build(root->l, a, num * 2);
    34     } else if(num * 2 <= n) {
    35         flag = true;
    36         root->l = new node(a);
    37         return;
    38     }
    39 }
    40 int res[50];
    41 int cnt=0;
    42 void levelOrder(node* root) {
    43     queue<node*> q;
    44     node* now = root;
    45     q.push(now);
    46     while(q.size()) {
    47         now = q.front();
    48         res[cnt++] = now->value;
    49         q.pop();
    50         if(now->l) {
    51             q.push(now->l);
    52         }
    53         if(now->r) {
    54             q.push(now->r);
    55         }
    56     }
    57 }
    58 int main() {
    59     cin >> n;
    60     for(int i = 1; i <= n; i++) {
    61         cin >> a[i];    
    62     }
    63     reverse(a + 1, a + n + 1);
    64     node* root = new node(a[1]);
    65     for(int i = 2; i <= n; i++) {
    66         flag = false;
    67         build(root, a[i], 1);
    68     }
    69     levelOrder(root);
    70     for(int i = 0; i < cnt; i++) {
    71         cout << res[i] << (i == n - 1?'
    ':' ');
    72     }
    73     
    74     return 0;
    75 }
    View Code

     

    L2-4 网红点打卡攻略 (25分)

     1.题意

      大家来网红点游玩,俗称“打卡”。在各个网红点打卡的方法称为“攻略”。你的任务就是从一大堆攻略中,找出那个能在每个网红点打卡仅一次、并且路上花费最少的攻略。

     输入格式:

    首先第一行给出两个正整数:网红点的个数 N和网红点之间通路的条数 M。随后 M 行,每行给出有通路的两个网红点、以及这条路上的旅行花费(为正整数),格式为“网红点1 网红点2 费用”,其中网红点从 1 到 N 编号;同时也给出你家到某些网红点的花费,格式相同,其中你家的编号固定为 0。再下一行给出一个正整数 K,是待检验的攻略的数量。随后 K 行,每行给出一条待检攻略,格式为:n V​1 V​2 ⋯ V​n,其中 n是攻略中的网红点数,V​i是路径上的网红点编号。这里假设你从家里出发,从V1开始打卡,最后从Vn回家。
    输出格式:
    在第一行输出满足要求的攻略的个数。
    在第二行中,首先输出那个能在每个网红点打卡仅一次、并且路上花费最少的攻略的序号(从 1 开始),然后输出这个攻略的总路费,其间以一个空格分隔。如果这样的攻略不唯一,则输出序号最小的那个。

     2.题解

      用一个二维数组存无向图的信息,bool数组判断是否去了每一个地点一次,更新最低花费。

     3.代码

     1 #include<bits/stdc++.h>
     2 #define N 205
     3 using namespace std;
     4 int n, m, k, nk;
     5 int g[N][N];
     6 int V[N];
     7 bool vis[N];
     8 int cnt, ans_i, ans_w = 0x3f3f3f3f;
     9 int main() {
    10     memset(g, -1, sizeof(g));
    11     cin >> n >> m;
    12     for(int i = 0; i < m; i++) {
    13         int u, v, w;
    14         cin >> u >> v >> w;
    15         g[u][v] = w;
    16         g[v][u] = w;
    17     }
    18     cin >> k;
    19     for(int i = 1; i <= k; i++) {
    20         memset(vis, false, sizeof(vis));
    21         cin >> nk;
    22         bool flag = true;
    23         for(int j = 1; j <= nk; j++) {
    24             cin >> V[j];
    25             vis[V[j]] = true;
    26         }
    27         V[0] = V[nk+1] = 0;
    28         if(nk != n) {
    29             continue;
    30         }
    31         for(int j = 1; j <= nk; j++) {
    32             if(!vis[j]) {
    33                 flag = false;
    34                 break;
    35             }
    36         }
    37         if(!flag) {
    38             continue;
    39         }
    40         int sumw = 0;
    41         for(int j = 0; j <= nk; j++) {
    42             if(g[V[j]][V[j+1]] > 0) {
    43                 sumw += g[V[j]][V[j+1]];
    44             } else {
    45                 flag = false;
    46                 break;
    47             }
    48         }
    49         if(!flag) {
    50             continue;
    51         }
    52         cnt++;
    53         if(ans_w > sumw) {
    54             ans_w = sumw;
    55             ans_i = i;
    56         }
    57     }
    58     cout << cnt << endl;
    59     cout << ans_i << " " << ans_w << endl;
    60     
    61     return 0;
    62 }
    View Code
  • 相关阅读:
    Freemarker中JS取Data-model的值的问题
    Jquery动态添加元素并给元素增加onchange相应
    [算法] 动态规划
    Linux安装mysql.8.0.12
    Linux命令
    [算法] 并查集
    Flume整合Kafka完成实时数据采集
    Kafka 单节点部署
    Spark Streaming——Flume实例
    Spark实战——日志分析
  • 原文地址:https://www.cnblogs.com/lvguapi/p/14089751.html
Copyright © 2011-2022 走看看