CCF能力认证历届第二题

201809-2. 买菜

解题思路:

主要就是判断小H和小W的装车时间段是否有重叠区间。关于判断重叠区间,对于给定的两个区间(a,b)和(c,d),显然当且仅当a≤d且b≥c时才会有重叠区间,而重叠区间长度L为min(b,d)-max(a,c),把所有重叠区间的长度进行累加求和,就可以知道俩人可以聊多长时间。

100分代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 void Input(int a[][2],int n);  //用来输入装车时间
 5 
 6 int main()
 7 {
 8     int n;
 9     cin >> n;   //时间段的数量
10     int H[n][2];   //小H的各个装车的时间段
11     Input(H,n);
12     int W[n][2];   //小W的各个装车的时间段
13     Input(W,n);
14     int ans = 0;
15     for (int i = 0; i < n; i++)
16     {
17         for (int j = 0; j < n; j++)
18         {
19             //对于给定的两个区间(a,b)和(c,d),显然当且仅当a≤d且b≥c时才会有重叠区间
20             if(H[i][0]<=W[j][1]&&H[i][1]>=W[j][0])   //判断有无重叠区间
21             {
22                 //重叠区间长度L为min(b,d)-max(a,c)
23                 ans += min(H[i][1],W[j][1])-max(H[i][0],W[j][0]);    //加上重叠区间
24             }
25         }
26     }
27     cout << ans << endl;
28     return 0;
29 }
30 
31 void Input(int a[][2],int n)
32 {
33     for (int i = 0; i < n; ++i)
34     {
35         cin >> a[i][0] >> a[i][1];
36     }
37 }

201803-2. 碰撞的小球

解题思路:

先吐槽一波,这道物理题也太长了吧,我截了3张图再把它们用photoshop拼起来的。建立俩个数组分别用来存取小球的位置和方向(规定方向向右为1,向左为-1)。每秒每个小球移动一个单位长度,小球每次移动之后都需要判断①该小球是否和其他小球发生碰撞,若发生了碰撞则碰撞的俩者都要改变方向;②该小球是否到达边界,若到达了边界也改变方向。最后输出每个小球的位置即可。     

100分代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6     int N,L,T;   //N为小球的个数,L为线段长度,计算T秒后小球的位置
 7     cin >> N >> L >> T;
 8     int a[N];   //n个小球的位置
 9     int b[N];   //n个小球的方向
10     for (int i = 0; i < N; i++)
11     {
12         cin >> a[i];
13         b[i] = 1;  //规定向右为1,向左为-1
14     }
15     while(T--)
16     {
17         for (int i = 0; i < N; i++)
18         {
19             a[i] += b[i];     //每个位置每次移动一个单位长度
20         }
21         for (int i = 0; i < N; i++)
22         {
23             for (int j = i+1; j < N; j++)  //判断小球是否和其他小球发生碰撞,若碰撞了则俩者均改变方向
24             {
25                 if(a[i]==a[j])
26                 {
27                     b[i] = -b[i];
28                     b[j] = -b[j];
29                 }
30             }
31             if(a[i]==0||a[i]==L)  //判断小球是否到达边界,若到达边界则改变方向
32             {
33                 b[i] = -b[i];
34             }
35         }
36     }
37     for (int i = 0; i < N; i++)
38     {
39         cout << a[i] << " ";
40     }
41     return 0;
42 }

201712-2. 游戏

解题思路:

这是一个约瑟夫环问题,我用队列来实现的。n个小朋友依次入队(假设围成了一个圈),count为计数器(用来记录报数)。排在队首的小孩报的数若是k的倍数或其个位数为k,则将该小孩淘汰。若小孩没有被淘汰则把他放入队尾继续转圈报数。

100分代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 bool Out(int count,int k)   //判断小孩是否被淘汰
 5 {
 6     if(count%k==0||count%10==k) //若一个小朋友报的数为k的倍数或个位数为k
 7     {
 8         return true;  //将该小孩淘汰出局
 9     }
10     return false;
11 }
12 
13 int main()
14 {
15     int n,k;
16     cin >> n >> k;
17     queue<int> q;
18     int count = 0;   //计数器
19     for (int i = 1; i <= n; i++)   
20     {
21         q.push(i);  //n个小朋友依次入队
22     }
23     while(q.size()>1)
24     {
25         count++;
26         int temp = q.front();  //读取队首元素
27         q.pop();    //删除队首元素
28         if(!Out(count,k))   //若该小孩没有被淘汰,则加入队尾继续转圈报数
29         {
30             q.push(temp);
31         }
32     }
33     cout << q.front() << endl;
34     return 0;
35 }

 201709-2. 公共钥匙盒

 

解题思路:

先定义一个教师结构体Teacher配合vector一起使用,里面有钥匙编号、使用钥匙的时间、标识符(0借1还),再创建一个钥匙列表key。vector先按还钥匙的时间升序排列,若还取钥匙的时间相同,则按先借后还排列,若多位老师还钥匙,则按钥匙编号升序排列。排序好以后,用for-each循环对vector进行遍历进行借还钥匙操作即可。最后对钥匙列表进行输出即可。

100分代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 struct Teacher
 5 {
 6     int key;    //钥匙编号
 7     int time;   //使用钥匙的时间
 8     int flag;   //设置标识符,0借,1还
 9 };
10 
11 bool Cmp(Teacher a,Teacher b)
12 {
13     if(a.time != b.time)
14     {
15         return a.time < b.time;    //先按还取钥匙的时间升序排序
16     }
17     else if(a.flag != b.flag)
18     {
19         return a.flag > b.flag;
20     }
21     else    //若多位老师还钥匙
22     {
23         return a.key < b.key;     //则按钥匙编号升序排列
24     }
25 }
26 
27 int main()
28 {
29     ios::sync_with_stdio(false);   //取消cin和stdin的同步
30     int N,K;
31     int key[1001];   //钥匙列表
32     cin >> N >> K;
33     vector<Teacher> v;
34     for (int i = 1; i <= N; i++)
35     {
36         key[i] = i;     //对钥匙进行赋初值
37     }
38     for (int i = 0; i < K; ++i)
39     {
40         int w,s,c;  //老师要使用的钥匙编号w、开始上课的时间s和上课的时长c
41         cin >> w >> s >> c;
42         v.push_back({w,s,0});    //
43         v.push_back({w,s+c,1});   //
44     }
45     sort(v.begin(),v.end(),Cmp);   
46     for(auto it:v)   
47     {
48         if(it.flag == 0)  //借钥匙
49         {
50             for (int i = 1; i <= N; i++)
51             {
52                 if(key[i] == it.key)
53                 {
54                     key[i] = 0;   //钥匙被借走了
55                     break;
56                 }
57             }
58         }
59         else    //还钥匙
60         {
61             for (int i = 1; i <= N; i++)
62             {
63                 if(key[i] == 0)
64                 {
65                     key[i] = it.key;   //把钥匙归还
66                     break;
67                 }
68             }
69         }
70     }
71     for (int i = 1; i <= N; i++)
72     {
73         cout << key[i] << " ";
74     }
75     return 0;
76 }

 201703-2. 学生排队

解题思路:

这题是利用vector来操作的,先对学生序号进行初始化,然后删除指定位置的学号,并将该指定学号插入到它的最终位置,最后对vector进行输出即可。

100分代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6     int n,m;//n个学生,m次移动 
 7     cin >> n >> m;
 8     vector<int> v; 
 9     for(int i = 0; i < n; i++)
10     {
11         v.push_back(i+1);   //初始化学生序号
12     }
13     for(int i = 0; i < m; i++)
14     {
15         int p,q;//学号p,移动q 
16         cin >> p >> q;
17         int j = 0;
18         while(i < m)
19         {
20             if(v[j]==p)
21             {
22                 v.erase(v.begin()+j);//删除指定位置的学号
23                 v.insert(v.begin()+j+q,p);//用insert函数将指定学号插入到最终位置。
24                 break;
25             }
26             j++;
27         }
28     } 
29     for(int i = 0; i < v.size(); i++)
30     {
31         cout << v[i] << " ";
32     }
33     return 0;
34 }

201612-2. 工资计算

解题思路:

对于这题,我这个菜鸡毫无方法可言,直接暴力破解。

100分代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6     int T,S; // T为税后工资,S为税前工资
 7     cin >> T;
 8     if (T <= 3500)
 9     {
10         S = T;
11     }
12     else if (T <= 4955)
13     {
14         S = ((T - 3500) / 97) * 100 + 3500;
15     }
16     else if (T <= 7655)
17     {
18         S = (T - 4955) / 90 * 100 + 5000;
19     }
20     else if (T <= 11255)
21     {
22         S = (T - 7655) / 80 * 100 + 8000;
23     }
24     else if (T <= 30755)
25     {
26         S = (T - 11255) / 75 * 100 + 12500;
27     }
28     else if (T <= 44755)
29     {
30         S = (T - 30755) / 70 * 100 + 38500;
31     }
32     else if (T <= 61005)
33     {
34         S = (T - 44755) / 65 * 100 + 58500;
35     }
36     else
37     {
38         S = (T - 61005) / 55 * 100 + 83500;
39     }
40     cout << S << endl;
41     return 0;
42 }

201609-2. 火车购票

解题思路:

用数组a来记录每排卖出的座位数,初始化为0。立一个flag用来判断能不能买到同一排相邻的座位。若需要购入的票数p加该排卖出的座位数小于5,则说明能买到同一排的相邻座位, 将flag改为true,并输出座位号。如果不能买到同一排的相邻座位,就按座位号升序来查找空座位。

100分代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6     int n;  //n为购票指令的数量
 7     cin >> n;
 8     int a[20];   //记录每排卖出的座位数
 9     memset(a,0,sizeof(a));   //全部初始化为0
10     while(n--)
11     {
12         int p;   //需要购入的票数
13         cin >> p;
14         bool flag = false;   //flag为true表示能买到同一排相邻的座位
15         for (int i = 0; i < 20; i++)   //假设能买到同一排的相邻座位
16         {
17             if(a[i]+p <= 5)
18             {
19                 for (int j = 0; j < p; j++)
20                 {
21                     if(j != p-1)
22                     {
23                         cout << i*5+a[i]+j+1 << " ";
24                     }
25                     else
26                     {
27                         cout << i*5+a[i]+j+1 << endl;
28                     }
29                 }
30                 a[i] += p;
31                 flag = true;
32                 break;
33             }
34         }
35         if(!flag)  //如果不能买到同一排的相邻座位,就按座位号从小到大来寻找空座位
36         {
37             int num = 0;
38             for (int i = 0; i < 20; i++)
39             {
40                 if(a[i] < 5)
41                 {
42                     num++;
43                     if(num == p)
44                     {
45                         cout << i*5+a[i]+1 << endl;
46                     }
47                     else
48                     {
49                         cout << i*5+a[i]+1 << " ";
50                     }
51                     a[i]++;
52                     i--;  //这一排可能还有空座位
53                 }
54             }
55         }
56     }
57     return 0;
58 }

未完待续····

原文地址:https://www.cnblogs.com/m17773572025/p/10068220.html