多多君最近在研究种编码算法:对于连续出现的字符,用变动的长度来表示,发现这样可以有效的减少存储的空间。
例如原字符串为:"AAAABBBCCDEEEE",2个C由4个A、3个B、1个D、4个E组成,编码后字符串为:“4A3B2C1D4E“,那么存储空间从14变成了10。多多君想测试这种算法的实际效果,于是找到了你,请你帮忙实现这种算法的解码过程。
共一行,一个字符串,表示需要进行解码的字符串,字符串由大小与字母纽成。(1<=字符串长度<=500)
共一行,一个字符串,表示字符串解码的结果。
10a1b1c
aaaaaaaaaabc
1P2D1p2d1P1D1d
PDDpddPDd
输入数据保证字符串均为合法编码后的字符串
思路:属于是试水简单题,设定变量num,num表示对应出现的次数,根据题意每一个最小的部分构成一定是 出现次数+出现字符,因此每次遇到字符输出 num个对应的字符即可。
#include
#include
using namespace std;
int main(){
string encoded_str;
cin >> encoded_str;
int num = 0;
for(char c:encoded_str){
if(c >= '0' && c <= '9'){
num = num * 10 + c - '0';
}else{
if(num){
cout << string(num, c);
}
num = 0;
}
}
return 0;
}
多多最近下载了一款飞机大战的游戏,多多可以通过游戏上的不同发射按键来控制飞机发射子弹:
按下A键,飞机会发射出2枚子弹,每个子弹会对命中的敌人造成1点固定伤害,但不能作用于同一个敌人。
按下B键,飞机会发射出1枚子弹,子弹会对命中的敌人造成巨额伤害并瞬间将其秒杀。
多多是一个游戏高手,总是能操控子弹命中想要命中的敌人。这个游戏一共有T个关卡,消灭消灭当前关卡全部敌人后,发射出去多余的子弹会小时,游戏会自动进入下一个关卡。
假设每个关卡都会在屏幕中同时出现N个敌人,这N个敌人所能承受的伤害也已经知道。多多想知道,每个关卡自己最少按几次发射按键就可以将敌人全部消灭?
第一行输入一个固定数字T(1<=T<=1000)表示关卡的总数量,N(1<=N<=2000)表示每个关卡出现的敌人数量。
接下来T行,每行有N个数字D1,D2,.....DN(1<=Di<=200),分别表示这N个敌人所能承受的伤害。
结果共有N行,每行一个数字,分别表示对于这个关卡,最少按几次发射按键就可以将敌人全部消灭。
输入输出示例仅供调试,后台判题数据一般不包含示例。
3 3
1 2 1
2 3 2
1 2 3
2
3
3
游戏共有3个关卡,每个关卡会出现3个敌人。
思路:分析一下,一次选择发射一个子弹秒杀一个敌人和两个子弹对两个敌人造成1点伤害,从效率上来说,一次发射两个子弹只有在两个敌人均为1点生命值时效率才会高于一发子弹秒杀一个敌人(在这种情况下,一次发射两个子弹一次就可以消灭两个生命值为1的敌人,而秒杀弹则需要两次)。换种理解方式,一次发射两个子弹造成的伤害总量只有2,在单体生命值大于等于2时,对上秒杀没有优势。
所以我们其实只需要统计一下1个个数,对于1的消灭,我们尽量采取两两同时消的策略,而对于剩余的大于1的部分,我们直接秒杀即可,如果1的个数为奇数个,我们也没有必要采用一次发射两个子弹,举例:余下1个1,与其他大于1的数,不妨设最小值2(因为值越小,秒杀的性价比越低),此时我们如果采用一次两颗子弹,那么就会变成0、1,此时想要清理完,还是需要一次秒杀,其实和两次秒杀(秒杀1和2)是一样的步数。而如果这个剩下的1继续和其他更大的值一起消,也只是重复该过程,最极端的情况就是 1 2 2 2 2 ... 2 2 2。
不失一般性,我们就假设有5个2,即 1 2 2 2 2 2,那么使用两个子弹消去的策略,过程为:
0 1 2 2 2 2
0 0 1 2 2 2
0 0 0 1 2 2
0 0 0 0 1 2
0 0 0 0 0 1
0 0 0 0 0 0
可以看到依旧是6步。而如果值比2大一点,则两发子弹就完全没有优势了。
#include
using namespace std;
int main(){
int T, N, idx, value, one_count, not_one_count;
cin >> T >> N;
while(T -- ){
one_count = not_one_count = 0;
for(idx = 0; idx < N; ++ idx){
cin >> value;
if(value == 1){
++ one_count;
} else{
++ not_one_count;
}
}
cout << (one_count / 2) + (one_count % 2) + not_one_count << endl;
}
return 0;
}
多多君开了一家自助餐厅,为了更好地管理库存,多多君每天需要对之前的客流量数据进行分析,并根据客流量的平均数和中位数来制定合理的备货策略。
输入共两行:
第一行一个整数N,表示餐厅营业总天数(0 第二行共N个整数,分别表示第i天的客流量 第一行长度为N,其中第i个值表示前i天客流量的平均值, 第二行长度为N,其中第i个值表示前i天客流量的中位数。 输入输出示例仅供调试,后台判题数据一般不包含示例 思路:对于平均值,我们只需要存储流量和求平均数即可,对于四舍五入,我们只需要对结果进行+0.5后取整即可。而输出中位数,当我们看了前i个数的时候,如果前i个数已经满足有序,那么只需要根据i的奇偶性来确定是取中间的一个数还是取中间两个数的平均值。而对于有序部分的维护,我们可以用插入排序来完成,复杂度为O(n^2)。 优化:用插排去维护的复杂度也很高,对于中位数问题,其实就是一个经典的数据流取中位数的问题,我们需要用大小堆来解决,现在有i个数,我们想求中位数,只要能够将较大的一半数放在小根堆里,将较小的一半放在大根堆里,这样可以保证小根堆堆顶是更大那一部分数的最小值,而大根堆堆顶是更小那一部分数的最大值。 在实际实现的时候,为了方便,当两个堆大小一样(包括都为空)的时候,我们就默认插到大根堆里(较小的那一半),如果发现大根堆的堆顶比小根堆的堆顶大,此时需要置换两个堆顶。 当两个堆大小不一样(为了取到中位数,我们必须保证两个堆大小不会大于1,同时因为我们默认会插大根堆,因此我们整体上应该满足大根堆的大小不会比小根堆大超过1),如果当前要入堆的数小于大根堆顶,即他是较小的一半,则这个数必须要入大根堆,且原大根堆顶必须弹出并入小根堆。如果当前要入堆的数大于等于大根堆顶,则直接入小根堆即可。 多多君准备了三个活动(分别编号A、B和C),每个活动分别有人数上限以及每个人参加的费用。 输出共2行 输入输出示例仅供调试,后台判题数据股不包含示例。 输入 输出 思路:动态规划问题,定义dp[attended_A][attended_B][attended_C]表示当前A活动参加了attended_A个人,B活动参加了attended_B个人,C活动参加了attended_C。用A[i]、B[i]、C[i]表示第i个人对A、B、C的意向。 那么考虑第i个人的时候,对于dp[attended_A][attended_B][attended_C]自然要考虑这个人是参加了A、B、C中的哪一个,即有如下转移方程: 。
输出描述
示例1
输入
5
1 2 3 4 10
输出
1 2 2 3 4
1 2 2 3 3
说明
输出结果四舍五入为整数
备注
1.输出结果四舍五入为整数;
#include
题4
参加团建的有N个人(分别编号1 ~N),每个人先投票选择若干个意向的活动,最终每个人只能参加其中一个。
多多君收集完投票结果后,发现如何安排成为了大难题:如何在满足所有人的意向的情况下,使得活动的总费用最少。
于是多多君找到了擅长编程的你,希望你能帮助找到一个合理的团建计划。输入描述
第一行,一个整数N,代表准备参加活动的人数。
(1<=N<=100)
接下来行,每行一个由"ABC"组成的字符串,其中第i行表示第i个人投票了哪几个活动。
(输入保证字符串非空,且由大写的"ABC"字符组成)
最后3行,每行两个整数,分别表示三个活动的人数上限以及每个人参加的费用。
(人数上限以及参与活动的费用均为不超过100的正整数)
输出描述
如果能满足所有人的要求,第一行输出"YES",第二行输出最少的总费用。
如果不能满足所有人的要求,第一行输出"NO",第二行输出最多能满足多少人。
示例15
A
B
C
AB
ABC
2 1
2 2
2 3
YES
9
#include