HAUT2021蓝桥杯专题练习第四周记录——贪心

贪心好难啊,证明啥都不会,全程膜拜大佬555
经过这次的练习也学到了很多吧,起码一些基础的贪心就知道了,但是吧,就这周说明白了是贪心还做不出来,更别说以后连贪心都不告诉了……算法之路,道阻且艰。

题目列表

  • HAUT2021蓝桥杯专题练习第四周记录——贪心
    • A 外币兑换(计蒜客T1524)
    • B 今年暑假不AC(HDU2037)
    • C 混合牛奶(P1208[USACO1.3])
    • D 最小距离字符串(计蒜客T1279)
    • E 程序设计:轻重搭配(计蒜客A2227)
    • F 纪念品分组(P1094[NOIP2007])
    • G 翻硬币(计蒜客T1395)
    • H Before an Exam(CF4B)
    • I 均分纸牌(P1031[NOIP2002])
    • J Milking cows(CF383A)
    • K Binary Period(CF1342B)
    • L 删数问题(P1106)
    • M Knights of a Polygonal Table(CF9948B)
    • N Strange Birthday Party(CF1470A)
    • O Heaters(CF1066B)
    • P Lawnmower(CF115B)
    • Q New Year Book Reading(CF500C)
    • R 序列(P1645)
    • S Clique Problem(CF527D)
    • T Make It Equal(CF1065C)
  • 总结

A 外币兑换(计蒜客T1524)

按照常规的前面几道超级水的题。
这题直接找出最大值的月然后全部换完就没了。
AC代码

#include <bits/stdc++.h>
using namespace std;
int main()
{double N, m = 0;cin >> N;for (int i = 0; i < 12; i++){double tmp;cin >> tmp;if (tmp > m)m = tmp;}printf("%.2f\n", m * N);return 0;
}

B 今年暑假不AC(HDU2037)

一道非常典型的贪心模板题,也是我为数不多会做的
按照结束时间进行排序,然后贪心选结束时间尽量早的就行了。

#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> P;
P p[200];
int main()
{int n;while (cin >> n){if (n == 0)break;for (int i = 0; i < n; i++)cin >> p[i].second >> p[i].first;int cnt = 0;//按照结束时间进行排序sort(p, p + n);int ed = 0;for (int i = 0; i < n; i++){//如果开始时间大于结束时间,就去看这一部if (ed <= p[i].second) {cnt++;ed = p[i].first;}}cout << cnt << endl;}return 0;
}

C 混合牛奶(P1208[USACO1.3])

贪心每次都买单价小的。
AC代码

#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> P;
P p[5100];
int main()
{int N, M;cin >> N >> M;for (int i = 0; i < M; i++)cin >> p[i].first >> p[i].second;//按照单价排序sort(p, p + M);int res = 0, cnt = 0;for (int i = 0; i < M; i++){//牛奶数量不够if (cnt + p[i].second <= N){cnt += p[i].second;res += p[i].second * p[i].first;}else{cnt = N - cnt;res += cnt * p[i].first;break;}}cout << res << endl;return 0;
}

D 最小距离字符串(计蒜客T1279)

对于每个字符都贪心选用最小的代价。
一共三个字符,也就分三种情况,全都相等(+0),或者有两个相等(+1),或者一个都不相等(+2)。
AC代码

#include <bits/stdc++.h>
using namespace std;
int main()
{string A, B, C;cin >> A >> B >> C;int n = A.length();int res = 0;for (int i = 0; i < n; i++){bool isok = false;if (A[i] == B[i] && A[i] != C[i])isok = true;if (A[i] == C[i] && A[i] != B[i])isok = true;if (B[i] == C[i] && A[i] != B[i])isok = true;if (A[i] == B[i] && A[i] == C[i]) //全都相等continue;if (isok) //有两个相等res++;else //都不同res += 2;}cout << res << endl;return 0;
}

E 程序设计:轻重搭配(计蒜客A2227)

因为重的人无法找到自己2倍体重的人,所以应该优先让轻的和比较轻的去匹配,比较重的和重的去匹配。这样能保证匹配的人数最多。证明的话不会
AC代码

#include <bits/stdc++.h>
using namespace std;
const int max_n = 500100;
int arr[max_n];
int n;
int main()
{cin >> n;for (int i = 0; i < n; i++)cin >> arr[i];sort(arr, arr + n);int cnt = 0;for (int i = 0, j = n / 2; i < n / 2; i++){while (j < n && arr[i] * 2 > arr[j]) //前面的比较大,后面的往后移j++;if (j >= n)break;cnt++;j++;}int res = n - cnt;cout << res << endl;return 0;
}

F 纪念品分组(P1094[NOIP2007])

先把便宜的和贵的尽可能多的进行匹配,然后再加上落单的纪念品。
AC代码

#include <bits/stdc++.h>
using namespace std;
int arr[30010];
int main()
{int w, n;cin >> w >> n;for (int i = 0; i < n; i++)cin >> arr[i];sort(arr, arr + n);int j = 0, cnt = 0;for (int i = n - 1; i >= 0; i--){//便宜和贵的匹配,用过的标记为-1if (arr[i] + arr[j] <= w && arr[i] != -1 && arr[j] != -1){arr[i] = -1;arr[j] = -1;cnt++;j++;}}for (int i = 0; i < n; i++){//记录落单的纪念物if (arr[i] != -1)cnt++;}cout << cnt << endl;return 0;
}

G 翻硬币(计蒜客T1395)

从左到右每次翻两个模拟进行下去就行了。保证一枚硬币不会被翻转超过两次(被动翻一次,主动翻一次),不然的话肯定不是最优解了。
AC代码

#include <bits/stdc++.h>
using namespace std;
int main()
{string s, goal;cin >> s >> goal;int cnt = 0;for (int i = 0; i < s.length() - 1; i++){if (s[i] != goal[i]){if (s[i] == '*')s[i] = 'o';elses[i] = '*';if (s[i + 1] == '*')s[i + 1] = 'o';elses[i + 1] = '*';cnt++;}}if (s[s.length() - 1] != goal[s.length() - 1])cout << "No Answer." << endl;elsecout << cnt << endl;return 0;
}

H Before an Exam(CF4B)

先每天把最少的时间都选上,然后遍历用剩余时间填满到最大值。
AC代码

#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> P;
//min max
P p[35];
int main()
{int d, sumTime;int smin = 0, smax = 0;cin >> d >> sumTime;for (int i = 0; i < d; i++){cin >> p[i].first >> p[i].second;smin += p[i].first;smax += p[i].second;}if (smin > sumTime || smax < sumTime) //不满足条件,直接退出{cout << "NO" << endl;return 0;}cout << "YES" << endl;sumTime -= smin; //每天最少选最小值for (int i = 0; i < d; i++){//剩下的值比最大值要大if (sumTime >= (p[i].second - p[i].first)) {sumTime -= (p[i].second - p[i].first);cout << p[i].second << " ";}else //剩下值不如最大值大{cout << p[i].first + sumTime << " ";sumTime = 0;}}cout << endl;return 0;
}

I 均分纸牌(P1031[NOIP2002])

先把平均值算出来,然后让数减去平均值看差了多少,只要总和0就至少要移动一次。
AC代码

#include <bits/stdc++.h>
using namespace std;
int arr[110];
int main()
{int n, sum = 0;cin >> n;for (int i = 0; i < n; i++){cin >> arr[i];sum += arr[i];}int tot = sum / n, res = 0;for (int i = 0; i < n; i++)arr[i] -= tot; //剩下的数sum = 0;for (int i = 0; i < n; i++){sum += arr[i]; //加上现在的数if (sum == 0)continue;//现在还不够res++;}cout << res << endl;return 0;
}

J Milking cows(CF383A)

这道题和 Number of Ways(CF466C) 这道题挺像的感觉,上次那个是找1/3的点,再找到2/3之后匹配每一个1/3,这道题是找到向右的牛,再找到向左的牛之后损失每一个向右的牛的牛奶量。
AC代码

#include <bits/stdc++.h>
using namespace std;
//和那道找三分之一和的题很像
int main()
{int n;cin >> n;long long sum = 0, res = 0;for (int i = 0; i < n; i++){int tmp;cin >> tmp;if (tmp == 1) //向右sum++;else //向左,有一个向右的,所有向左的都得损失res += sum;}cout << res << endl;return 0;
}

K Binary Period(CF1342B)

除去全是0和全是1的情况,其余答案都可以由"01"字符串构成。如果目标有一个数,那我就给他一个"01"。这样就能保证,目标串是我这个串的子串了,而且肯定是有周期的。
AC代码

#include <bits/stdc++.h>
using namespace std;
int main()
{string s = "01";int T;cin >> T;while (T--){string goal;cin >> goal;string res;int n = goal.size(), sum = 0;for (int i = 0; i < n; i++)sum += goal[i] - '0'; //计算1的个数if (sum == 0 || sum == n) //全是0或者全是1cout << goal << endl;else{string res;for (int i = 0; i < n; i++)res += s;cout << res << endl;}}return 0;
}

L 删数问题(P1106)

每次都去删前面比后面大的数。
分析过程放到代码里面了。
AC代码

#include <bits/stdc++.h>
using namespace std;
/*  分析过程//都与自己后边的数比较1  7  5  4  3  8小 大 大 大 小  无 这样就直接扫一遍就可以把大的全部删除了(7 5 4)剩下的是按照增序排序的,那么就直接删除比较大的数就是答案
*/
int main()
{string s;cin >> s;int k;cin >> k;int n = s.size();for (k; k > 0; k--){for (int i = 0; i < s.size(); i++){if (s[i] > s[i + 1]) //如果后面的数比前面的数小,删除前面的数{s.erase(i, 1);break;}}}while (s[0] == '0') //前导零问题s.erase(0, 1);if (s.size() == 0)s = "0";cout << s << endl;return 0;
}

M Knights of a Polygonal Table(CF9948B)

让骑士,尽可能的去杀比自己能力低,并且带着的钱比较多的骑士,这样就能保证每个骑士获得的钱比较多了。
详细的思路放到代码里面了。
AC代码

#include <bits/stdc++.h>
using namespace std;
const int max_n = 100100;
struct Knight
{//能力 金币数 结果金币数 自身的序号long long p, c, res, number;
} knight[max_n];int main()
{int n, k;cin >> n >> k;for (int i = 0; i < n; i++){cin >> knight[i].p;knight[i].number = i;}for (int i = 0; i < n; i++){cin >> knight[i].c;knight[i].res = knight[i].c;}//按能力值(p)排序sort(knight, knight + n, [](Knight k1, Knight k2) {if (k1.p != k2.p)return k1.p < k2.p;return k1.c < k2.c;});//保留待鲨的骑士vector<int> tmp;tmp.push_back(knight[0].c);for (int i = 1; i < n; i++) //第i个可以要前i-1个的c{int m = 0, t = k;while (t--) //把前面这k个鲨了{knight[i].res += tmp[m];m++;if (m == tmp.size()) //如果已经把比自己弱的鲨完了break;}tmp.push_back(knight[i].c);//大到小排序sort(tmp.begin(), tmp.end(), [](int v1, int v2) {return v1 > v2;});if (tmp.size() > k) //如果数量大于ktmp.pop_back();}//按照序号还原顺序sort(knight, knight + n, [](Knight k1, Knight k2) {return k1.number < k2.number;});for (int i = 0; i < n; i++)cout << knight[i].res << " ";cout << endl;return 0;
}

N Strange Birthday Party(CF1470A)

礼物只有一个,而且序号大的可以选择比自己序号小的礼物,也就是说,序号大的可以选择便宜的礼物,那么就让序号比较大的先选择是送钱还是送礼物。
AC代码

#include <bits/stdc++.h>
using namespace std;
const int max_n = 300100;
int k[max_n];
int c[max_n];int main()
{int t;cin >> t;while (t--){int n, m;cin >> n >> m;for (int i = 1; i <= n; i++)cin >> k[i];for (int i = 1; i <= m; i++)cin >> c[i];//从大到小排序,sort(k + 1, k + 1 + n, [](int a, int b) {return a > b;});long long res = 0, r = 1;for (int i = 1; i <= n; i++){if (c[k[i]] > c[r]) //相比送钱,买礼物更便宜,所以选择送礼物并且让礼物指针右移{res += c[r];r++;}elseres += c[k[i]];}cout << res << endl;}return 0;
}

O Heaters(CF1066B)

这题,但是做懵了可能,楞是理解错题意了。
题目大致意思就是让覆盖所有区间,那么直接就找看哪里没有被覆盖,然后在覆盖的的范围里面找尽可能往右的灯,这样需要的灯就会比较少了。
AC代码

#include <bits/stdc++.h>
using namespace std;
const int max_n = 1010;
int arr[max_n];
//题目大意:覆盖所有区间
int main()
{int n, r;cin >> n >> r;for (int i = 1; i <= n; i++)cin >> arr[i];int res = 0;for (int i = 1; i <= n; i++){bool isok = false;for (int j = min(n, i + r - 1); j >= max(i - r + 1, 1); j--) //找最右边能开灯的地方{if (arr[j] == 1) //开灯{res++;i = j + r - 1; //直接到最后面覆盖不到的地方找isok = true;break;}}if (!isok){cout << "-1" << endl;return 0;}}cout << res << endl;return 0;
}

P Lawnmower(CF115B)

容易知道的是,奇数行要从左向右,偶数行要从右向左。
有一个做法是保留最左边和最后边的草,然后直接一下到头就行了。但是我这样做的时候WA了,因为有些地方需要注意,像空行
下面是参考一个大佬做法写的。一步一步走,计算曼哈顿距离。
AC代码

#include <bits/stdc++.h>
using namespace std;
char Map[155][155];int main()
{int n, m;cin >> n >> m;for (int i = 1; i <= n; i++){for (int j = 1; j <= m; j++)cin >> Map[i][j];}//奇数往右,偶数向左//上次的行数和列数int starti = 1, startj = 1, res = 0;for (int i = 1; i <= n; i++){if (i % 2 == 1) //奇数行{for (int j = 1; j <= m; j++){if (Map[i][j] == 'W') //如果这一行有草,那么直接推到草那里{res += abs(starti - i) + abs(startj - j);starti = i;startj = j;}}}else //偶数行{for (int j = m; j >= 1; j--){if (Map[i][j] == 'W') //如果这一行有草,那么直接推到草那里{res += abs(starti - i) + abs(startj - j);starti = i;startj = j;}}}}cout << res << endl;return 0;
}

Q New Year Book Reading(CF500C)

书的顺序就是第一次读到这本书的顺序,先找好顺序,然后可以放到vector里面,使用erase和insert两个函数进行书的调换。
AC代码

#include <bits/stdc++.h>
using namespace std;
int w[520];        //书重
int d[1010];       //读哪一本书
vector<int> order; //摆书的顺序
int arr[520];      //辅助记录顺序int main()
{int n, m;cin >> n >> m;memset(arr, 0, sizeof(arr));for (int i = 1; i <= n; i++)cin >> w[i];int j = 1;for (int i = 1; i <= m; i++){cin >> d[i];if (arr[d[i]] == 0){arr[d[i]]++;order.push_back(d[i]);j++;}}int res = 0;for (int i = 1; i <= m; i++) //读书顺序{for (j = 0; j < order.size(); j++) //找书{if (d[i] != order[j])res += w[order[j]]; //加上前面的书重else                    //找到书了之后更新顺序{order.erase(order.begin() + j);order.insert(order.begin(), d[i]);break;}}}cout << res << endl;return 0;
}

R 序列(P1645)

放进结构体里面按照右边界排序,然后遍历一下结构体里面的范围,看里面是否有这么多的数,没有的话从右往左取数。
AC代码

#include <bits/stdc++.h>
using namespace std;
struct QJ
{int l, r, c;} qj[1010];
int vis[1010];
int main()
{int n;cin >> n;memset(vis, 0, sizeof(vis));for (int i = 0; i < n; i++)cin >> qj[i].l >> qj[i].r >> qj[i].c;//按照r排序sort(qj, qj + n, [](QJ q1, QJ q2) {return q1.r < q2.r;});int res = 0;for (int i = 0; i < n; i++){int cnt = 0;for (int j = qj[i].l; j <= qj[i].r; j++) //先看里面数字够不够那么多{if (vis[j])qj[i].c--;}if (qj[i].c > 0) //不够,因为是至少有ci个数,所以有可能ci<0{for (int j = qj[i].r; j >= qj[i].l; j--) //从右向左取{if (!vis[j]){vis[j] = 1;qj[i].c--;res++;if (qj[i].c == 0) //够了break;}}}}cout << res << endl;return 0;
}

S Clique Problem(CF527D)

这道题进行移项处理,转换成了区间覆盖问题,区间覆盖问题直接把右边界进行排序。
当然这都是大佬说的,我就只会按这写……
AC代码

#include <bits/stdc++.h>
using namespace std;
const int max_n = 200010;
struct Point
{//坐标 权值 左边界 有边界//xi - wi >= xj + wj//l >= rint x, w, l, r;
} p[max_n];
int main()
{int n;cin >> n;for (int i = 0; i < n; i++){cin >> p[i].x >> p[i].w;p[i].l = p[i].x - p[i].w;p[i].r = p[i].x + p[i].w;}//按照右边界边界排序sort(p, p + n, [](Point p1, Point p2) {if (p1.r != p2.r)return p1.r < p2.r;return p1.l < p2.l;});//区间覆盖问题int res = 0, last = -1 << 30;for (int i = 0; i < n; i++){if (p[i].l >= last){res++;last = p[i].r;}}cout << res << endl;return 0;
}

T Make It Equal(CF1065C)

找出最高的塔和最低的塔,然后慢慢砍到最低的那个塔就行了。如果砍了一层发现还有剩余,那么就继续砍下一层。总之尽可能多的使用完就行了。
AC代码

#include <bits/stdc++.h>
using namespace std;
const int max_n = 200100;
int h[max_n];
int cnt[max_n];
int main()
{int n, k;cin >> n >> k;//最低的塔高和最高的塔高int min = 1 << 30;int max = 0;for (int i = 0; i < n; i++){cin >> h[i];if (h[i] < min)min = h[i];if (h[i] > max)max = h[i];cnt[h[i]]++; //h[i]这么高的塔有多少个}int res = 0, sum = 0;//从高的往低的砍for (int i = max; i > min; i--){cnt[i] += cnt[i + 1]; //砍到了第i层if (sum + cnt[i] > k){res++;sum = cnt[i]; //如果不能砍了,就另加一次,来砍这一刀}elsesum += cnt[i];}if (sum == 0) //如果sum==0代表不用砍剩下的1刀了,反之需要再砍一刀cout << res << endl;elsecout << res + 1 << endl;return 0;
}

总结

贪心题不知道怎么贪心的话是怎么想都想不出来,知道了之后就感觉好水(
因为过年的问题,做完了前面几道题之后就直接给自己放假玩去了233后面的题是后来再写的,不过感觉还行,学到了很多吧,虽然不知道自己会不会用,反正一点一点来得了。
下周DP,挺好。

HAUT2021蓝桥杯专题练习第四周记录——贪心相关推荐

  1. 【蓝桥杯专题】 贪心(C++ | 洛谷 | acwing | 蓝桥)

    菜狗现在才开始备战蓝桥杯QAQ 文章目录 [蓝桥杯专题] (C++ | 洛谷 | acwing | 蓝桥) 1055. 股票买卖 II AcWing 104. 货仓选址 传递糖果 AcWing 112 ...

  2. 蓝桥杯官网刷题记录python

    蓝桥杯官网刷题记录python 由于很多题都会在2020.2021.2022年省赛出现,有的在前面文章里做过的这里就不会再说了 一.空间 小蓝准备用 256MB 的内存空间开一个数组,数组的每个元素都 ...

  3. 【蓝桥杯专题】 DP(C++ | 洛谷 | acwing | 蓝桥)

    菜狗现在才开始备战蓝桥杯QAQ 文章目录 编程实现动态规划的状态转移方程时, 务必分清楚阶段. 状态与决策, 三者应该按照由外向内的顺序依次循环!! ----蓝书 背包问题 01背包 AcWing 3 ...

  4. 蓝桥杯专题之并查集篇

    题目列表: 2020年:网络分析,七段码 合根植物 1.网络分析 题目描述 小明正在做一个网络实验.他设置了 n 台电脑,称为节点,用于收发和存储数据.初始时,所有节点都是独立的,不存在任何连接.小明 ...

  5. 蓝桥杯专题-试题版-【十进制转十六进制】【十六进制转八进制】【十六进制转十进制】【数的读法】

    点击跳转专栏=>Unity3D特效百例 点击跳转专栏=>案例项目实战源码 点击跳转专栏=>游戏脚本-辅助自动化 点击跳转专栏=>Android控件全解手册 点击跳转专栏=> ...

  6. 蓝桥杯专题-试题版含答案-【荷兰国旗问题】【正三角形的外接圆面积】【比较字母大小】【车牌号】

    点击跳转专栏=>Unity3D特效百例 点击跳转专栏=>案例项目实战源码 点击跳转专栏=>游戏脚本-辅助自动化 点击跳转专栏=>Android控件全解手册 点击跳转专栏=> ...

  7. 蓝桥杯专题(一)《C语言》

    一.年号字串 题目链接https://www.lanqiao.cn/problems/605/learning/ 小明用字母 A 对应数字 1,B 对应 2,以此类推,用 Z 对应 26.对于 27 ...

  8. 蓝桥杯 历届试题 翻硬币(贪心)

    历届试题 翻硬币 时间限制:1.0s   内存限制:256.0MB 问题描述 小明正在玩一个"翻硬币"的游戏. 桌上放着排成一排的若干硬币.我们用 * 表示正面,用 o 表示反面( ...

  9. 蓝桥杯算法训练KAc给糖果贪心-python题解

    KAC给糖果(贪心) 问题描述 kAc有n堆糖果,每堆有A[i]个. kAc说你只能拿m次糖果,聪明的你当然想要拿最多的糖果来吃啦啦啦~ //第二天,kAc问你还想吃糖果么?(嘿嘿嘿)说着眼角路出奇怪 ...

最新文章

  1. ES6中的Promise详解
  2. FPGA学习之路—应用程序—原码二位乘法器及Verilog代码分析
  3. 网络连接的netstat命令
  4. 使用友元,编译出错fatal error C1001: INTERNAL COMPILER ERROR (compiler file 'msc1.cpp', line 1786) 的解决...
  5. [RBA开发系列一] 建立http 请求的process
  6. [bbk2193] 第34集 - Chapter 09-Optimizing Sore Perations(03)
  7. c语言linux系统宏,Linux下C语言中的预定义宏
  8. mysql 数据类型总结
  9. 免费好用的录屏工具 —— EVCapture
  10. 【福利】论机房如何关闭方正软件保护卡
  11. 数学原理(The Principles of Mathmatics)
  12. Java接口组装一台计算机编写各组件厂商分别实现CPU,EMS,HardDisk接口
  13. 基于MinimaxAlpha-Beta剪枝和强化学习的播棋(Mancala)AI
  14. 13 Python函数进阶
  15. 1005: 整数幂 Java
  16. Android仿QQ列表滑动
  17. 亲情友情爱情:《悲惨世界》第四部《卜吕梅街的柔情和圣德尼街的史诗》/人性:《悲惨世界》第五部《冉阿让》摘录...
  18. LTE-5G学习笔记8---PRACH参数规划
  19. 空气源热泵控制系统解决方案
  20. ORCALE DDL,DML,DQL命令

热门文章

  1. mybatis-sql语句莫名其妙被加上limit分页条件或未执行查询条件
  2. 面试第一问:简单做个自我介绍吧,怎么回答才让面试官频频点头?
  3. 【hardware】什么是H桥电路?
  4. GDT、GDTR、LDT、LDTR的理解 [zz]
  5. Machine Learning 机器学习
  6. java多用户商城系统架构之第一篇——总的介绍
  7. 浏览器提示代理服务器出现问题,或则地址有误
  8. OSChina 周三乱弹 —— 国家命运与个人命运
  9. configure: error: Cannot find ldap libraries in /usr/lib
  10. win10下如何使用的debug