51nod一个贪心专题,大多数都是见过的套路,做题找找感觉,有些题解思路懒得写了,直接贴毕姥爷的直播题解了

A 低买高卖

考虑股票市场,一共有n天。对于第i天,B君知道股票的价格是每单位a[i]元在每一天,B君可以选择买入一个单位的股票,卖出一个单位的股票,或者什么都不做。

刚开始B君有无穷多的钱,但是没有任何股票。问n天之后B君最多可以赚多少钱。(1 <= n <= 200000)(1 <= a[i] <= 10000)

输入

第一行一个整数n表示天数。

接下来一行n个整数,表示每天的价钱。

输出

一行一个整数表示最多可以赚的钱数。

输入样例

9
10 5 4 7 9 12 6 2 10

输出样例

20

思路, 这道题是个很好的题目,也算是一个不错的套路贪心题, 这题很容易想到的是n^2 DP, dp[i][j]代表前i天j个股票的价钱,但是会t, 所以可以贪心来做, 我们假设每一天都在卖股票,但是不可能每一天都在卖的之前肯定要买股票后面才能卖,因此转换一下把卖出去转换为持有,把持有转换为买入, 对于当前价格B而言,只要前面有比这个价格低的价格A,那么当前情况A买入B卖出一定盈利,但是A买入B卖出不一定是最优解,所以为了有后悔药吃,就再push两个B进入优先队列,一个表示卖出,一个表示买入。每天都卖出,每次累加差值就可以了。累加很多个差分值肯定会得到最优解的。因为A买入B卖出B买入C卖出 和 A买入C卖出 效果一样

代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
priority_queue<int> pq;
int main()
{
int n, x;
while(~scanf("%d", &n))
{
while (pq.size())
pq.pop();
int ans = 0;
for(int i = 1; i <= n; i++)
{
scanf("%d", &x);
pq.push(-x);
ans += x + pq.top();
pq.pop();
}
printf("%d\n", ans);
}
return 0;
}

C 接水问题

n个人一起排队接水,第i个人的重要性是a[i],需要b[i]的时间来接水。

1 <= n <= 100000

0 <= b[i] <= 1000

0 <= a[i] <= 1000

同时只能有一个人接水,正在接水的人和没有接水的人都需要等待。

完成接水的人会立刻消失,不会继续等待。

你可以决定所有人接水的顺序,并希望最小化所有人等待时间乘以自己的重要性a[i]的总和。

输入

第一行一个整数n。

以下n行,每行两个整数a[i]和b[i]。

输出

一行一个整数表示答案。

输入样例

4
1 4
2 3
3 2
4 1

输出样例

35

思路: 思路很简单,经典套路,直接比较相邻两个, 这题要注意 a与b都可能为0, 之前想着把除法转为乘法让a不为0即分子不为0就行, 但是这样是有问题的, 对于 \(\frac{a_1}{b_1}\)本应该是\(>\frac{0}{0}\)的,但是转为乘法之后他们他们就是 \(0 = 0\)了,排序显然会出现问题,因此要么把a = 0.b = 0的样例排除掉,要么特判相等的时候,让他返回 a1 < a2,即通过特判a来让0在前面。

代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn = 1e5 + 5;
typedef long long ll;
struct node
{
ll a, b;
bool operator < (const node &tmp) const
{
return tmp.a*b < a*tmp.b || (tmp.a*b == a*tmp.b && a < tmp.a);
}
}x[maxn];
int main()
{
int n;
while(~scanf("%d", &n))
{
for(int i = 1; i <= n; i++)
{
scanf("%lld%lld", &x[i].a, &x[i].b);
}
sort(x+1, x+1+n);
ll pre = 0, ans = 0;
for(int i = 1; i <= n; i++)
{
pre = pre + x[i].b;
ans = ans + pre*x[i].a;
}
printf("%lld\n", ans);
}
return 0;
}

D做任务一

B君和m个人一起,要完成n个任务,在这个题中,m个人会看着这B君,自己什么都不做。

第i个任务有一个开始时间s[i]和结束时间e[i](保证s[i]<=e[i]),一个人完成两个任务的时间区间,不能有交集,但是可以首尾相连。(参考样例)

换句话说,如果一个人依次完成了(s[1], e[1]) (s[2], e[2]) (s[3], e[3])这3个任务,那么这3个任务需要满足s[1]<=e[1]<=s[2]<=e[2]<=s[3]<=e[3]。

同一个任务只能完成一次,并且中间不能换人。

问B君一个人最多可以完成多少个任务。

(单组 n <= 100000)

(所有 n 求和 <= 200000)

(开始时间和结束时间,都是非负整数,且在int范围内。)

(开始时间 <= 结束时间,如果等于的话,意味着这个任务可以瞬间被做完,但是不能没有人做)

输入

多组数据,第一行是数据组数。

每组数据的第一行两个整数n, m分别表示任务数,和人数。

以下n行,每行两个整数表示任务的开始时间和结束时间。

输出

对于每组数据输出一个整数

表示一个人最多可以完成多少个任务。

输入样例

2
2 1
1 3
2 4
2 1
1 3
3 5

输出样例

1
2

注意以下两个思路, 一定要记得把另一个端点按照相同的方法排序, 因此会有 s==e的情况,如果另一个端点随机排序,会错误,可以自己举例看一下。

思路1:



代码1:


#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 1e5 + 20;
struct node
{
int l, r;
bool operator < (const node &tmp) const
{
if(r != tmp.r)
return r < tmp.r;
else
return l < tmp.l;
}
}a[maxn];
int main()
{
int _, n, m;
cin >> _;
while(_--)
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%d%d", &a[i].l, &a[i].r);
sort(a + 1, a + 1 + n);
int ans = 0, r = 0;
for (int i = 1; i <= n; i++)
{
if (a[i].l >= r) r = a[i].r, ans++;
}
printf("%d\n", ans); }
return 0;
}

思路1:



代码2:


#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn = 100000 + 5;
struct node
{
int l, r;
bool operator < (const node &a) const
{
if(l != a.l)
return l < a.l;
else
return r < a.r;
}
}a[maxn];
int main()
{
int t;
cin >> t;
while(t--)
{
int n, m;
scanf("%d%d", &n,&m);
for(int i = 1; i <= n; i++)
{
scanf("%d%d", &a[i].l, &a[i].r);
}
sort(a+1, a+1+n);
int r = 0, ans = 0;
for(int i = 1; i <= n; i++)
{
if(a[i].l >= r) r = a[i].r, ans++;
else if(a[i].r < r) r = a[i].r;
}
printf("%d\n", ans);
}
return 0;
}

E做任务三

B君和m个人一起,要完成n个任务,在这个题中,B君和m个人,什么都不做。

第i个任务有一个开始时间s[i]和结束时间e[i](保证s[i]<=e[i]),一个人完成两个任务的时间区间,不能有交集,但是可以首尾相连。(参考样例)

换句话说,如果一个人依次完成了(s[1], e[1]) (s[2], e[2]) (s[3], e[3])这3个任务,那么这3个任务需要满足s[1]<=e[1]<=s[2]<=e[2]<=s[3]<=e[3]。

同一个任务只能完成一次,并且中间不能换人。

B君和m个人,想知道要想完成这些任务,至少需要几个人?

(单组 n <= 100000)

(所有 n 求和 <= 200000)

(开始时间和结束时间,都是非负整数,且在int范围内。)

(开始时间 <= 结束时间,如果等于的话,意味着这个任务可以瞬间被做完,但是不能没有人做)

输入

多组数据,第一行是数据组数。

每组数据的第一行两个整数n, m分别表示任务数,和人数。

以下n行,每行两个整数表示任务的开始时间和结束时间。

输出

对于每组数据输出一个整数

表示完成这些任务至少需要多少人。

输入样例

4
2 1
1 3
2 4
2 1
1 3
3 5
2 1
1 3
2 2
4 1
1 2
2 2
2 2
2 3

输出样例

2
1
2
1

思路1:



#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn = 100000 + 5;
struct node
{
int l, r;
bool operator < (const node &a) const
{
if(l != a.l)
return l < a.l;
else
return r < a.r;
}
}a[maxn];
int main()
{
int t;
cin >> t;
while(t--)
{
priority_queue<int> pq;
int n, m;
scanf("%d%d", &n,&m);
for(int i = 1; i <= n; i++)
{
scanf("%d%d", &a[i].l, &a[i].r);
}
sort(a+1, a+1+n);
int r = 0, ans = 0;
for(int i = 1; i <= n; i++)
{
if(!pq.size()) pq.push(-a[i].r), ans++;
else
{
if (a[i].l >= -pq.top())
{
pq.pop();
}
else
{
ans++;
}
pq.push(-a[i].r);
}
}
printf("%d\n", ans);
}
return 0;
}

思路2:



这个思路代码就先不写了, 第一个思路比较容易写也好理解

[ACM]51nod 贪心专题的更多相关文章

  1. 51nod贪心算法教程

    51nod确实是一个好oj,题目质量不错,wa了还放数据,学习算法来说挺好的,这次我做了几个水的贪心,虽然水,但是确实都很典型. 教程链接:http://www.51nod.com/tutorial/ ...

  2. nyoj 218 Dinner(贪心专题)

    Dinner 时间限制:100 ms  |  内存限制:65535 KB 难度:1   描述 Little A is one member of ACM team. He had just won t ...

  3. nyoj 106背包问题(贪心专题)

    背包问题 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 现在有很多物品(它们是可以分割的),我们知道它们每个物品的单位重量的价值v和重量w(1<=v,w< ...

  4. nyoj 448 寻找最大数(贪心专题)

    寻找最大数 时间限制:1000 ms  |  内存限制:65535 KB 难度:2   描述 请在整数 n 中删除m个数字, 使得余下的数字按原次序组成的新数最大, 比如当n=920813467185 ...

  5. nyoj 71 独木舟上的旅行(贪心专题)

    独木舟上的旅行 时间限制:3000 ms  |  内存限制:65535 KB 难度:2   描述 进行一次独木舟的旅行活动,独木舟可以在港口租到,并且之间没有区别.一条独木舟最多只能乘坐两个人,且乘客 ...

  6. nyoj 14 会场安排问题(贪心专题)java

    会场安排问题 时间限制:3000 ms  |  内存限制:65535 KB 难度:4   描述 学校的小礼堂每天都会有许多活动,有时间这些活动的计划时间会发生冲突,需要选择出一些活动进行举办.小刘的工 ...

  7. nyoj 14 会场安排问题(贪心专题)

    会场安排问题 时间限制:3000 ms  |  内存限制:65535 KB 难度:4   描述 学校的小礼堂每天都会有许多活动,有时间这些活动的计划时间会发生冲突,需要选择出一些活动进行举办.小刘的工 ...

  8. 51nod贪心算法入门-----完美字符串

    约翰认为字符串的完美度等于它里面所有字母的完美度之和.每个字母的完美度可以由你来分配,不同字母的完美度不同,分别对应一个1-26之间的整数. 约翰不在乎字母大小写.(也就是说字母F和f)的完美度相同. ...

  9. 51nod贪心算法入门-----任务分配问题

    任务执行顺序 有N个任务需要执行,第i个任务计算时占R[i]个空间,而后会释放一部分,最后储存计算结果需要占据O[i]个空间(O[i] < R[i]). 分析: 可以抽象成,从一个整数开始,每次 ...

随机推荐

  1. Spark源码分析 – SparkEnv

    SparkEnv在两个地方会被创建, 由于SparkEnv中包含了很多重要的模块, 比如BlockManager, 所以SparkEnv很重要 Driver端, 在SparkContext初始化的时候 ...

  2. window下cmd的宽度调整

    一直被cmd的宽度这么了好些年,刚才搜索了下,还真可以设置.标题栏右键属性,调整屏幕缓冲区宽度,只要足够长就不会换行了,然后调整窗口大小-宽度,不能超过屏幕缓冲区宽度,当小于屏幕缓冲区的时候,就会显示 ...

  3. PushState+Ajax实现简单的单页面应用SPA

    http://www.helloweba.com/view-blog-386.html 单页面应用(Single Page Application)简称SPA,使用SPA构建的应用优点有用户体验好.速 ...

  4. vim使用winmanager整合nerd tree和taglist

    winmanager插件安装 • 插件简介 winmanager is a plugin which implements a classical windows type IDE in Vim-6. ...

  5. 函数对象[条款18]---《C++必知必会》

    有时需要一些行为类似于函数指针的东西,但函数指针显得笨拙.危险而且过时(让我们承认这一点).通常最佳方式是使用函数对象(function object)取代函数指针. 与智能指针一样,函数对象也是一个 ...

  6. Linux系统常用命令示例

    1.在跟下创建一个目录,目录的名字为data # mkdir /data2.在data目录里创建一个文件,文件名为yunjisuan.txt # touch /data/yunjisuan.txt3. ...

  7. 《mysql必知必会》读书笔记--触发器及管理事务处理

    触发器 触发器是MySQL响应DELETE,INSERT,UPDATE而自动执行的一条MySQL语句,其他语句不支持触发器. 创建触发器时,需要4个条件: 唯一的触发器名 触发器关联的表 触发器应该响 ...

  8. HDU - 3338 Kakuro Extension (最大流求解方格填数)

    题意:给一个方格,每行每列都有对白色格子中的数之和的要求.每个格子中的数范围在[1,9]中.现在给出了这些要求,求满足条件的解. 分析:本题读入和建图比较恶心... 用网络流求解.建立源点S和汇点T, ...

  9. CIFAR和SVHN在各CNN论文中的结果

    CIFAR和SVHN结果 加粗表示原论文中该网络的最优结果. 可以看出DenseNet-BC优于ResNeXt优于DenseNet优于WRN优于FractalNet优于ResNetv2优于ResNet ...

  10. ARKit 研究笔记一

    软件需求:Xcode9.x .blender 硬件需求:iphone 6s + 系统:iOS 11 + 技能储备: ARKit .SceneKit(苹果提供的3d游戏库) 或 SpriteKit(苹果 ...