打热水
打热水
原题链接:https://oj.haizeix.com/problem/506
寝室楼里只有热水间能接热水,且每天烧水机器只在指定时间工作,去晚了机器就关掉了,每天晚上去接热水的同学能排起小长队。
某天在总计四个烧水机中,坏了三个只剩下一台机器能打水了。
现在有 n 名同学等待接水,因为每名同学所带的水壶有大有小,规格各不相同所以他们每人的接水时间分别为 Ti,
现求一个顺序,使得所有接水的同学平均等待接水时间最小,等待接水时间为该同学之前接水的同学所花费时间和。
输入
第一行一个整数 n。(1 ≤ n ≤ 30)
第二行 n 个整数表示 Ti。(1 ≤ Ti ≤ 2000)
输出
第一行输出排队顺序
第二行输出平均等待时间,结果保留两位小数。
样例:
121056 12 1 99 1000 234 33 55 99 812
123 2 7 8 1 4 9 6 10 5291.90
参考代码1234567891011121314151617181920212223242526272829303132333435363738#include<iostream>#include<algorithm>#include<cstdio>using namespace std;struct node { int cnt;//打水同学的编号 int time;//所需的打水时间};node stu[35];int n;//同学的数量bool cmp(const node &a, const node &b) { return a.time < b.time;}int main() { //1.数据存储 cin >> n; for (int i = 1; i <= n; ++i) { cin >> stu[i].time; stu[i].cnt = i; } //2.数据处理 sort(stu + 1, stu + n + 1, cmp); int sum = 0;//总打水时间 int now = 0;//某个同学的打水等待时间 for (int i = 1; i <= n; ++i) ...
两人过河
两人过河
原题链接:https://oj.haizeix.com/problem/508
有 n 个人希望在晚上通过一座桥。
在任何时刻,最多只能有两个人在桥上,并且必须要带着手电筒才能过桥。
现在只有一个手电筒,所以必须安排某种顺序,使得手电筒可以被带回去让更多的人过桥。
每个人都有不同的过桥时间,两个人一起过桥所用的时间等于其中较慢的一个人的过桥时间。
现求所有人过桥的最短时间。
输入
第一行一个整数 n。(1 ≤ n ≤ 1000)
接下来 n 行,每行一个整数表示第 i 人的过桥时间 Ti。(1 ≤ Ti ≤ 100)
输出
输出所有人过桥的最短时间。
样例:
12345415210
117
让 1, 2 先过桥,然后让 1 回来,让 5,10 过桥,然后 2 回来再和 1 一起过桥,时间为 2+1+10+2+2=17。
思路==思路==:让时间短的人优先过桥,作为工具人。
递归解决问题
有时使用1个人当工具人过桥时间较短,有时使用2个人当工具人过桥时间较短
取两种方案中速度较快的一种(将两种方案结合起来)
参考代码设最快的过桥时间为num[0]、次快过桥时间为num[1]、次慢过桥时间为num[i - 1]、最慢过桥时间为num[i]:
则有:
n = 1时,最快过桥时间为num[0]
n = 2时,最快过桥时间为num[1]
n = 3时,最快过桥时间为num[1] + num[0] + num[2]
n > 3时,最快过桥时间为
方案1(2个工具人):num[1] + num[0] + num[i] + num[1](此时两个工具人都在起点)
方案2(1个工具人):num[i] + num[0] + num[i - 1] + num[0](此时工具人在起点)
1234567891011121314151617181920212223242526272829#include<iostream>#include<algorithm>using namespace std;int n, num[1005];int ans;int main() { cin >> n; for (int i = 0; i & ...
智力大冲浪
智力大冲浪
原题链接:https://oj.haizeix.com/problem/509
小伟报名参加中央电视台的智力大冲浪节目。
本次挑战赛吸引了众多参赛者,主持人为了表彰大家的勇气先奖励每个参赛者 m 元,接下来主持人宣布了比赛规则:
首先,比赛时间分为 n 个时段 (n ≤ 500),它又给出了很多小游戏,每个小游戏都必须在规定期限 ti 前完成 (1 ≤ ti ≤ n )。
如果一个游戏没能在规定期限前完成,则要从奖励费 m 元中扣去一部分钱 wi,不同的游戏扣去的钱是不一样的。
当然,每个游戏本身都很简单保证每个参赛者都能在一个时段内完成,而且都必须从整时段开始。主持人只是想考考每个参赛者如何安排组织自己做游戏的顺序。作为参赛者,小伟很想赢得冠军当然更想赢取最多的钱。
输入:
第一行为 m,表示一开始奖励给每位参赛者的钱
第二行为 n,表示有 n 个小游戏
第三行有 n 个数,分别表示游戏 1 到 n 的规定完成期限
第四行有 n 个数,分别表示游戏 1 到 n 不能在规定期限前完成的扣款数
输出:
输出小伟能赢取最多的钱
样例:
12341000074 2 4 3 1 4 670 60 50 40 30 20 10
19950
思路
优先完成扣钱多的任务
对于每个可以完成的任务,尽量靠后完成
参考代码1
元音字母
元音字母
原题链接:https://oj.haizeix.com/problem/477
给定一个只包含大写字母 A − Z 的字符串,找到相邻两个元音字母之间间隔最大的距离。注:元音字母为 AEIOU
思路:记录上一个元音字母的位置last,以及当前访问的元音字母的位置i,计算最大距离判断是否更新ans的结果。如此循环
题解1逻辑有些混乱
1234567891011121314151617181920212223bool check(char c) { if (c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U') return true; return false;}int func(string str) { int index[2]; int maxlen = 0; int flag = 0; for (int i = 0; i < str.length(); ++i) { if (flag && check(str[i])) { index[1] = i; int newlen = index[1] - index[0]; if (newlen > maxlen) maxlen = newlen; index[0] = index[1]; } if (!flag && check(str[i])) {//第1个元音字母 index[0] = i; flag = 1; } } return maxlen;}
题解2对首个元音字母的处理 进行逻辑优化
12345678910111213141516171819bool check(char c) { if (c == 'A' || c = ...
乒乓球
乒乓球
原题链接:https://oj.haizeix.com/problem/479
国际乒联前主席沙拉拉自从上任以来就立志于推行一系列改革,以推动乒乓球运动在全球的普及。
其中 11 分制改革引起了很大的争议,有一部分球员因为无法适应新规则只能选择退役。华华就是其中一位,他退役之后走上了乒乓球研究工作,意图弄明白 11 分制和 21 分制对选手的不同影响。在开展他的研究之前,他首先需要对他多年比赛的统计数据进行一些分析,所以需要你的帮忙。
华华通过以下方式进行分析,首先将比赛每个球的胜负列成一张表,然后分别计算在 11 分制和 21 分制下,双方的比赛结果(截至记录末尾)。
比如现在有这么一份记录,(其中 W 表示华华获得一分,L 表示华华对手获得一分):
1WWWWWWWWWWWWWWWWWWWWWWLW
在 11 分制下,此时比赛的结果是华华第一局 11 比 0 获胜,第二局 11 比 0 获胜,正在进行第三局,当前比分 1 比 1。
而在 21 分制下,此时比赛结果是华华第一局 21 比 0 获胜,正在进行第二局,比分 2 比 1。
如果一局比赛刚开始,则此时比分为 0 比 0。直到分差大于或者等于 2,才一局结束。
你的程序就是要对于一系列比赛信息的输入(WL形式),输出正确的结果。
输入:每个输入文件包含若干行字符串,字符串有大写的 W、L 和 E 组成。其中 E 表示比赛信息结束,程序应该忽略 E 之后的所有内容。
输出:输出由两部分组成,每部分有若干行,每一行对应一局比赛的比分(按比赛信息输入顺序)。其中第一部分是 11 分制下的结果,第二部分是 21 分制下的结果,两部分之间由一个空行分隔。
样例:
12WWWWWWWWWWWWWWWWWWWWWWLWE
12345611:011:01:121:02:1
试解版本1代码冗余!且没有数据的保存(输出后立刻丢失)
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051#include<iostream>using namespace std;void func11(string str) { if (str[0] == ' ...
保龄球
保龄球
原题链接:https://oj.haizeix.com/problem/480
打保龄球是用一个滚球去打击十个站立的柱,将柱击倒。
一局分十轮,每轮可滚球一次或多次,以击倒的柱数为依据计分。
一局得分为十轮得分之和,而每轮的得分不仅与本轮滚球情况有关,还可能与后续一两轮的滚球情况有关。即某轮某次滚球击倒的柱数不仅要计入本轮得分,还可能会计入前一两轮得分。具体的滚球击柱规则和计分方法如下:
若某一轮的第一次滚球就击倒全部十个柱,则本轮不再滚球(若是第十轮则还需另加两次滚球,不妨称其为第十一轮和第十二轮,并不是所有的情况都需要滚第十一轮和第十二轮球)。该轮得分为本次击倒柱数 10 与以后两次滚球所击倒柱数之和。
若某一轮的第一次滚球未击倒十个柱,则可对剩下未倒的柱再滚球一次。如果这两次滚球击倒全部十个柱,则本轮不再滚球(若是第十轮则还需另加一次滚球),该轮得分为这两次共击倒柱数 10 与以后一次滚球所击倒柱数之和。
若某一轮两次滚球未击倒全部十个柱,则本轮不再继续滚球,该轮得分为这两次滚球击倒的柱数之和。
总之,若—轮中一次滚球或两次滚球击倒十个柱,则本轮得分是本轮首次滚球开始的连续三次滚球击倒柱数之和(其中有一次或两次不是本轮滚球)。若一轮内二次滚球击倒柱数不足十个,则本轮得分即为这两次击倒柱数之和。
下面以实例说明如下(字符“/”表示击倒当前球道上的全部的柱):
1234轮 1 2 3 4 5 6 7 8 9 10 11 12击球情况 / / / 72 9/ 81 8/ / 9/ / 8/每轮得分 30 27 19 9 18 9 20 20 20 20累计总分 30 57 76 85 103 112 132 152 172 192
现在请你编写一个保龄球实时计分程序,用来计算和显示结束后的得分情况。
样例:
1/ / / 72 9/ 81 8/ / 9/ / 8/
1192
试解思路:先将所有数据输入存储起来,再去从前向后遍历 进行数据的处理
123456789101112131415161718192021222324252627282930313233343536373839#incl ...
冰壶比赛
冰壶比赛
原题链接:https://oj.haizeix.com/problem/481
在冰壶比赛中给出一个目标点 P 以及一个规定的正整数 r,每一局由甲和乙两队轮流投冰壶各 88 次后该局比赛结束。
此时哪一方的冰壶最终离目标点最近,该方得分另一方不得分。
得分方离目标点 P 距离小于或等于 r,位置较另一队所有冰壶都更接近目标点 P 的冰壶都可以得1分(比赛最多进行 10 局)
双方之间的某局比赛结束后落后一方可以弃权,此时比赛不再进行下去。
已知某一局结束时,双方的每个冰壶离目标点 P 的距离以及正整数 r,请写一个程序判断两队之间每一局比赛的得分,以及总得分。
输入
第 1 行一个正整数 r。
以下有若干行,表示对局,每一行 8 个正整数;
第 2 行的第 j 个数表示第 1 局比赛结束时,甲方的第 j 个冰壶距离目标点 P 的距离;
第 3 行的第 j 个数表示第 1 局比赛结束时,乙方的第 j 个冰壶距离目标点 P 的距离;
……
第 2k 行的第 j 个数表示第 k 局比赛结束时,甲方的第 j 个冰壶距离目标点 P 的距离;
第 2k+1 行的第 j 个数表示第 k 局比赛结束时,乙方的第 j 个冰壶距离目标点 P 的距离;
如果有一方中途弃权,则最后一行(偶数行)只有一个整数 −1,表示此时发生弃权情况;
比赛最多进行 10 局,若输入多于 21 行,请忽略 21 行后的所有内容。
输出
输出若干行,每行两个整数,中间以冒号分隔,表示每一局比赛甲乙双方的比分(甲得分在前)。
最后一行有 2 个整数,中间以冒号分隔,表示甲乙双方比赛的最终得分(甲得分在前)。
样例:
123456789//样例185 20 18 19 3 15 13 320 2 17 12 5 18 10 1120 3 4 1 2 11 9 21 15 19 9 8 14 11 1015 2 10 1 19 14 3 1815 17 21 19 24 32 19 26-1
12340:10:03:03:1
123456789101112131415161718192021//样例285 20 18 19 3 15 13 320 2 17 12 5 18 10 1120 3 4 1 2 11 9 21 15 19 9 8 14 11 1015 2 10 1 19 ...
垃圾邮件
垃圾邮件
原题链接:https://oj.haizeix.com/problem/483
一个有效的邮箱地址包含以下几点要求:
地址是由小写英文字母、英文的句号 “.” 和一个 “@” 字符组成的字符串。
紧靠 “@” 字符左边和右边的两个字符必须是一个字母,地址的第一个和最后一个字符不能是 “.”。
比如,”mama@ta..ta” “m.am.a@t..a.t..a” 和 “m@t” 都是有效的,而 “ma@” “@ma.ma” “.mama@tata” 和 “ma.ma@tata.tata.” 不是。
可以这样来打乱自己的自制:
将 “@” 符号替换为 “at”
在地址的任意位置(包括首尾)插入0或1次 “nospam”
现在需要编写一个程序,给定一个打乱过的地址,还原出所有可能的原始有效地址。
输入
一行一个打乱过的地址,长度不超过 100。
输出
按照字典序从小到大输出所有可能的原始有效地址,每行输出一个。
样例:
1nospammamaattatahr
1234mama@tatahrmamaatt@ahrnospammama@tatahrnospammamaatt@ahr
参考代码==思路==:对string的操作
先在给定的字符串中寻找nospam字符串,有几个删除几个,将所有的可能都存在ans数组中。
将at字符替换为@,如果有很多at则逐个尝试,将所有可能的情况存到ans数组中
对ans中所有的情况,按照字典序进行sort排序后输出。
1
柱状统计图
柱状统计图
原题链接:https://oj.haizeix.com/problem/484
给出一些字符串,总长度不超过1000,统计其中大写字母的个数,并按照给定样例格式输出。
输入
一堆字符串,每两个字符串之间可能用空格、换行隔开。
输出
参照样例输出柱状统计图,每个 * 表示出现一次,注意每行不要有多余的空格。
样例:
12ABC ABC.DEF()G GCC XY354342aaaCaa aaaaaaaabcdbcd
123456 * * ** * * ** * * * * * * * *A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
参考代码思路:
大写字母统计string str[1000] cin >> str;,对应的字符数量增加num[str['A']]++;
统计结果输出
确定图形高度(最多数量的字母的数量)
每一行确定输出到哪里
进行输出
1
均分纸牌
均分纸牌
原题链接:https://oj.haizeix.com/problem/485
有 N 堆纸牌,编号分别为 1,2,…,N。
每堆上有若干张,但纸牌总数必为 N 的倍数。可以在任一堆上取若干张纸牌,然后移动。
移牌规则为:
在编号为 1 堆上取的纸牌,只能移到编号为 2 的堆上;在编号为 N 的堆上取的纸牌,只能移到编号为 N−1 的堆上;
其他堆上取的纸牌,可以移到相邻左边或右边的堆上。
现在要求找出一种移动方法,用最少的移动次数使每堆上纸牌数都一样多。
例如 N=4,4堆纸牌数分别为:① 9 ② 8 ③ 17 ④ 6
移动 3 次可达到目的:
从 ③ 取 4 张牌放到 ④ (9,8,13,10)-> 从 ③ 取 3 张牌放到 ②(9,11,10,10)-> 从 ② 取 1 张牌放到①(10,10,10,10)
输入
第一行一个整数 N。(1 ≤ N ≤ 100)
第二行 N 个整数,A1, A2, …,An。(N堆纸牌,每堆纸牌初始数,1 ≤ Ai ≤ 10000)
输出
输出一个整数表示所有堆均达到相等时的最少移动次数。
样例:
1249 8 17 6
13
参考代码123456789101112131415161718192021222324#include <iostream>using namespace std;int sum;int n, num[105];//牌堆信息int main(){ cin >> n; for (int i = 0; i < n; ++i) { cin >> num[i]; sum += num[i]; } int avg = sum / n; int ans = 0;//需要移动的次数 for (int i = 0; i < n - 1; ++i) { if (num[i] != avg) { ans++; num[i + 1] += num[i] - avg; num[i] = avg; } } cout << ans <<endl; return 0;}