算法题解三

贪心

独木舟
输入
​ 第一行一个整数 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;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值