贪心
独木舟
输入
第一行一个整数 w,表示独木舟的载重量。(80≤w≤200)
第二行一个整数 n,表示旅游人数。 (1≤n≤30000)
接下来 n 行,每行一个数表示 ai,即每个人的重量 (5≤ai≤w)
输出
输出一个数表示最少需要的独木舟数量。
样例输入
100
9
90
20
20
30
50
60
70
80
90
样例输出
6
#include<iostream>
#include <algorithm>
using namespace std;
int m, n, num[30005], ans;
int main() {
cin >> m >> n;
for (int i = 0; i < n; i++) {
cin >> num[i];
}
sort(num, num + n);
for (int i = 0, j = n - 1; i <= j; j--) {
if (num[i] + num[j] <= m) {
i++;
ans++;
}
else {
ans++;
}
}
cout << ans << endl;
return 0;
}
最大整数
输入
第一行一个整数 n。(1≤n≤100000)
第二行 n 个不超过 int 类型范围的正整数。
输出
输出一个数表示组成的最大整数。
样例输入
3
121 12 96
样例输出
9612121
#include<iostream>
#include <algorithm>
#include <string>
using namespace std;
string num[100005];
int n;
bool cmp (const string &a, const string &b) {
return a + b > b + a;
}
int main() {
cin >> n;
for (int i = 0; i < n; i++) {
cin >> num[i];
}
sort(num, num + n, cmp);
for (int i = 0; i < n; i++) {
cout << num[i];
}
cout << endl;
return 0;
}
打水排队
输入
第一行一个整数 n。(1≤n≤30)
第二行 n 个整数表示 Ti。(1≤Ti≤2000)
输出
第一行输出排队顺序。
第二行输出平均等待时间,结果保留两位小数。
样例输入
10
56 12 1 99 1000 234 33 55 99 812
样例输出
3 2 7 8 1 4 9 6 10 5
291.90
// 将时间从小到大排序, 利用结构体将时间与原顺序对应; 排序后排完得顺序输出原来的序号;
#include<iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
struct node {
int ind, num;
};
int n, now, sum;
node stu[35];
bool cmp(const node &a, const node &b) {
return a.num < b.num;
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> stu[i].num;
stu[i].ind = i;
}
sort(stu + 1, stu + n + 1, cmp);
for (int i = 1; i <= n; i++) {
if (i != 1) {
cout << " ";
}
cout << stu[i].ind;
sum += now;
now += stu[i].num;
}
printf("\n%.2f\n", (double)sum / n);
return 0;
}
两人过河
题目描述
有 n 个人希望在晚上通过一座桥。在任何时刻,最多只能有两个人在桥上,并且必须要带着手电筒才能过桥。现在只有一个手电筒,所以必须安排某种顺序,使得手电筒可以被带回去让更多的人过桥。每个人都有不同的过桥时间,两个人一起过桥所用的时间等于其中较慢的一个人的过桥时间。现求所有人过桥的最短时间。
输入
第一行一个整数 n。(1≤n≤1000)
接下来 n 行,每行一个整数表示第 i 人的过桥时间 Ti。(1≤Ti≤100)
输出
输出所有人过桥的最短时间。
样例输入
4
1
5
2
10
样例输出
17
#include<iostream>
#include <algorithm>
using namespace std;
int num[1005], n, ans;
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> num[i];
}
sort(num + 1, num + n + 1);
for (int i = n; i > 0; i -= 2) {
if (i == 1) {
ans += num[1];
break;
}
else if (i == 2) {
ans += num[2];
break;
}
else if (i == 3) {
ans += num[2] + num[1] + num[3];
break;
}
else {
ans += min(num[i] + num[1] + num[i - 1] + num[1], num[2] + num[1] + num[i] + num[2]);
}
}
cout << ans << endl;
return 0;
}
枚举
火柴棒等式
题目描述
给出 n 根火柴棒,可以拼出多少个形如 a+b=c 的等式。
等式中的 a,b,c 是用火柴棒拼出的整数(不能有前导零),数字和符号使用的火柴棒数量如下:
0:6
1:2
2:5
3:5
4:4
5:5
6:6
7:3
8:7
9:6
+:2
=:2
有以下注意事项:
1.加号和等号各自需要两根火柴棒
2.如果 a≠b,则 a+b=c 和 b+a=c 视为不同的等式,a,b,c 均不小于 0。
3. n 根火柴棒必须全部用上。
输入
共一行一个整数 n。(1≤n≤24)
输出
输出能组成的等式数。
样例输入
14
样例输出
2
#include<iostream>
using namespace std;
int num[10] = {6, 2, 5, 5, 4, 5, 6, 3, 7, 6};
int n, ans;
int func(int x) {
if (x == 0) {
return 6;
}
int t = 0;
while (x) {
t += num[x % 10];
x /= 10;
}
return t;
}
int main() {
cin >> n;
for (int i = 0; i < 1111; i++) {
for (int j = 0; j < 1111; j++) {
if (func(i) + func(j) + func(i + j) + 4 == n) {
ans++;
//cout << i << " + " << j << " = " << i + j << endl;
}
}
}
cout << ans << endl;
return 0;
}
楼层编号
题目描述
小明外出旅游住在了某宾馆中,该宾馆有一个被诅咒的数字 t,该数字不会出现在宾馆的楼层数中。
例如,当 t=3 时,3,13,31,33 等等的楼层都是不存在的,楼层编号为 1,2,4,5,…,所以实际上 4 楼的真实层数是 3 楼。
已知小明预定了 m 层的房间,现求该层的真实层数是多少(m 一定是宾馆中存在的楼层)。
输入
共一行两个整数 m,t。(1≤m≤100000,0≤t≤9)
输出
输出真实楼层。
样例输入
14 3
样例输出
12
#include<iostream>
using namespace std;
int m, n, ans;
int func(int x) {
while (x) {
int t = x % 10;;
if (t == n) {
return 0;
}
x /= 10;
}
return 1;
}
int main() {
cin >> m >> n;
for (int i = 1; i <= m; i++) {
if (func(i)) {
ans++;
}
}
cout << ans << endl;
return 0;
}
比例简化
题目描述
在社交媒体上,经常会看到针对某一个观点同意与否的民意调查以及结果。例如,对某一观点表示支持的有 1498 人,反对的有 902 人,那么赞同与反对的比例可以简单的记为 1498:902。
不过,如果把调查结果就以这种方式呈现出来,大多数人肯定不会满意。因为这个比例的数值太大,难以一眼看出它们的关系。对于上面这个例子,如果把比例记为 5:3,虽然与真实结果有一定的误差,但依然能够较为准确地反映调查结果,同时也显得比较直观。
现给出支持人数 A,反对人数 B,以及一个上限 L,请你将 A 比 B 化简为 A’ 比 B’,要求在 A’ 和 B’ 均不大于 L 且 A’ 和 B’ 互质(两个整数的最大公约数是 1)的前提下,A’/B’≥A/B 且 A’/B’−A/B 的值尽可能小。
输入
共一行三个整数 A,B,L,每两个整数之间用一个空格隔开,分别表示支持人数、反对人数以及上限。
输出
共一行两个整数 A’,B’,中间用一个空格隔开,表示化简后的比例。
样例输入
1498 902 10
样例输出
5 3
// 枚举答案
#include<iostream>
using namespace std;
int m, n, l, mm, nn;
double raw, now = 99999999;
int main() {
cin >> m >> n >> l;
raw = (double)m / n;
for (int i = 1; i <= l; i++) {
for (int j = 1; j <= l; j++) {
double t = (double)i / j;
if (t >= raw && t - raw < now - raw) {
mm = i, nn = j, now = t;
}
}
}
cout << mm << " " << nn << endl;
return 0;
}
奶牛碑文
题目描述
约翰和他的奶牛在大草原漫游,在一块石头上发现了一些有趣的碑文。碑文似乎是一个神秘古老的语言,只包括三个大写字母 C,O,W。尽管约翰看不懂,但是令他高兴的是,C,O,W 的顺序形式构成了一句他最喜欢的奶牛单词 “COW”。现在,他想知道有多少次 COW 出现在文本中。如果 COW 内穿插了其他字符,只要 COW 字符出现在正确的顺序,约翰也不介意。甚至,他也不介意出现不同的 COW 共享一些字母。例如,CWOW 出现了 1 次 COW,CCOW 算出现了 2 次 COW,CCOOWW 算出现了 8 次 COW。
输入
第一行一个整数 N。(1≤N≤105)
第二行为含有 N 个字符的字符串,字符只可能是 C,O,W。
输出
输出 COW 作为输入字符串的字串出现的次数(不一定是连续的)。
答案可能会很大。
样例输入
6
COOWWW
// 空间换时间
#include<iostream>
#include <cstring>
using namespace std;
int n, numc[100005], numw[100005];
char str[100005];
long long ans;
int main() {
cin >> n >> str;
for (int i = 0; str[i]; i++) {
if (i > 0) {
numc[i] = numc[i - 1];
}
if (str[i] == 'C') {
numc[i]++;
}
}
for (int i = strlen(str); i >= 0; i--) {
numw[i] = numw[i + 1];
if (str[i] == 'W') {
numw[i]++;
}
}
for (int i = 0; str[i]; i++) {
if (str[i] == 'O') {
ans += numc[i] * numw[i];
}
}
cout << ans << endl;
return 0;
}
金币
题目描述
国王将金币作为工资,发放给忠诚的骑士。第一天,骑士收到一枚金币;之后两天(第二天和第三天),每天收到两枚金币;之后三天(第四、五、六天),每天收到三枚金币;之后四天(第七、八、九、十天),每天收到四枚金币……;这种工资发放模式会一直这样延续下去:当连续 N 天每天收到 N 枚金币后,骑士会在之后的连续 N+1 天里,每天收到 N+1 枚金币。
现在给出一个日期 x,求第一天到第 x 天骑士总共获得的金币数。
输入
输入一行一个整数 x。(1≤x≤104)
输出
输出骑士总共获得的金币数。
样例输入
10
样例输出
30
#include<iostream>
using namespace std;
int n, ans, cnt;
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
ans += i;
cnt++;
if (cnt == n) { // 每天给一次,判断是否结束
break;
}
}
if (cnt == n) break;
}
cout << ans;
return 0;
}