挺早之前做好一直想写一篇博客分享一下,但是后来给忘了…C++方向一共十二道编程题,可能和别的方向有一些出入。题目总体的难度不大,有些题有些小坑,适合进阶者练练手,本文比较长,建议直接进github看代码,如有错误欢迎指出,也欢迎大家讨论!
代码都扔在Github
了 -> Github
题目列表:
① 调整队列
② 分饼干
③ 双核处理
④ 堆砖块
⑤ 奇怪的表达式求值
⑥ 小易记单词
⑦ 工作安排
⑧ 凃棋盘
⑨ 消除重复元素
⑩ 赶去公司
⑪ 集合
⑫ 魔力手环
[Problem 1]:调整队列
在幼儿园有n个小朋友排列为一个队伍,从左到右一个挨着一个编号为(0~n - 1)。其中有一些是男生,有一些是女生,男生用’B’表示,女生用’G’表示。小朋友们都很顽皮,当一个男生挨着的是女生的时候就会发生矛盾。作为幼儿园的老师,你需要让男生挨着女生或者女生挨着男生的情况最少。你只能在原队形上进行调整,每次调整只能让相邻的两个小朋友交换位置,现在需要尽快完成队伍调整,你需要计算出最少需要调整多少次可以让上述情况最少。例如:GGBBG->GGBGB->GGGBB
这样就使之前的两处男女相邻变为一处相邻,需要调整队形2次
输入描述 :
输入数据包括一个长度为n且只包含G和B的字符串.n不超过50.
输出描述 :
输出一个整数,表示最少需要的调整队伍的次数
输入例子 :
GGBBG
输出例子 :
2
这题只分两种情况,男女相挨着的情况最少,那么就是G都在左边或者B都在左边,两种情况模拟一下然后min就是答案了。
实现代码:
#include<iostream>
//#include<map>
#include<algorithm>
#include<string>
#include<vector>
//#include<numeric>
//#include<cmath>
//#include<set>
using namespace std;
string QUEUE;
int result, Num_G = 0, Num_B = 0;
vector<int>Result_G, Result_B;
int main() {
cin >> QUEUE;
size_t len = QUEUE.size();
int i = 0;
int sum_G = 0, sum_B = 0;
//auto it = QUEUE.begin(), END = QUEUE.end();
while (i < len) {
if (QUEUE[i] == 'G') {
++Num_G; Result_G.push_back(i);
}
if (QUEUE[i] == 'B') {
++Num_B; Result_B.push_back(i);
}
++i;
}
for (i = 0; i < Num_G; ++i)sum_G += (Result_G[i] - i);
for (i = 0; i < Num_B; ++i)sum_B += (Result_B[i] - i);
result = min(sum_B, sum_G);
cout << result << endl;
return 0;
}
[Problem 2]:分饼干
易老师购买了一盒饼干,盒子中一共有k块饼干,但是数字k有些数位变得模糊了,看不清楚数字具体是多少了。易老师需要你帮忙把这k块饼干平分给n个小朋友,易老师保证这盒饼干能平分给n个小朋友。现在你需要计算出k有多少种可能的数值
输入描述 :
输入包括两行:
第一行为盒子上的数值k,模糊的数位用X表示,长度小于18(可能有多个模糊的数位)
第二行为小朋友的人数n
输出描述 :
输出k可能的数值种数,保证至少为1
输入例子 :
9999999999999X
3
输出例子 :
4
最笨也是最直接的方法当然是X用0~9然后挨个试一遍,牛客讨论区看到有人这样能AC,但是我死活过不了不知道为什么…然后用了另一种方法,是从讨论区看到的思路,1个数在除以一个数的过程中,是从前往后一位一位除的,能否除的尽,要看前面的余数和当前的数的组合能否除的尽,所以要记录前面一位所有的余数可能性。比如 :
X2
2
X除2的余数可能是0 ,1,是0的可能性为X=0,2,4,6,8 五种,取1的可能性为X=1,3,5,7,9 也是五种,这个时候再看个位数的2,2和前面的余数0/1的组合为02/12,也就是说到了这一位余数为0的可能性为上一位余数为0/1两种情况总数的和,因为02,12余2都是0,k=5+5=10种。
感觉有点类似于推公式,找规律,不那么容易想到。
也看到有另一种思路的,将k分拆为多个数,比如123X45,那么可能总数就是123000+X45(X枚举0~9),若(123000%n+X45%n)=n的倍数,则此种情况成立,最后算一个总和,大家可以尝试一下。
实现代码:
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<ctype.h>
#include<sstream>
//#include<numeric>
//#include<cmath>
//#include<set>
using namespace std;
long long sync[10001], remain[10001]; //每一位数对应余数取值的可能性
int main() {
string s;
int n;
cin >> s;
cin >> n;
sync[0] = 1;
int s_size = s.size();
for (int i = 0; i < s_size; ++i) {
memset(remain, 0, sizeof(remain));
for (int j = 0; j < n; j++) { //这一位所能取的余数的可能性(0...n-1)
for (int k = 0; k < 10; k++) { //这一位能取的数,当然是0~9啦
if (isdigit(s[i]) && s[i] - '0' != k) continue;
//isdigit 判断是否为0~9的数字
//若该位为k,则计算所有可能取值,否则只计算这一种取值
remain[((j * 10) + k) % n] += sync[j];
//计算当前值和前一位余数的取值组合产生的余数
}
}
memcpy(sync, remain, sizeof(sync)); //与余数对应的取值同步
}
cout << sync[0] << endl; //最后一位余数为0的的取值
}
[Problem 3]:双核处理
一种双核CPU的两个核能够同时的处理任务,现在有n个已知数据量的任务需要交给CPU处理,假设已知CPU的每个核1秒可以处理1kb,每个核同时只能处理一项任务。n个任务可以按照任意顺序放入CPU进行处理,现在需要设计一个方案让CPU处理完这批任务所需的时间最少,求这个最小的时间。
输入描述 :
输入包括两行:
第一行为整数n(1 ≤ n ≤ 50)
第二行为n个整数length[i](1024 ≤ length[i] ≤ 4194304),表示每个任务的长度为length[i]kb,每个数均为1024的倍数。
输出描述 :
输出一个整数,表示最少需要处理的时间
输入例子 :
5
3072 3072 7168 3072 1024
输出例子 :
9216
其实这是一道简单的动态规划题,双核处理,我们只要处理其中的一半,然后和剩下的一半对比时间哪个更少就行了,把它转化为经典的0-1背包模型,其实就是代价
和所获价值
都是length[i]
,思路在注释里了,solve
部分优化了空间,优化的部分建议大家参考hihocoder-1038
这道题,过程写得可以说是非常详细了1038# 0-1背包。
实现代码:
#include<iostream>
//#include<map>
#include<algorithm>
//#include<string>
#include<vector>
#include<numeric>
//#include<cmath>
//#include<set>
using namespace std;
const int MAX_SIZE =