贪心策略笔记

贪心策略笔记

概念:在学贪心之前,我们要先了解贪心是什么东西。首先,贪心是一种策略,一种思想。在对问题进行求解时,总是能作出当前看来最好的选择,但是它不是从整体最优考虑,它所作出的仅是在某种意义上的局部最优解。
         贪心没有固定的算法框架,它在不同的题目中出现的形式都是不一样的。但是它算法设计的关键是贪心策略的选择。也就是说想要贪心,你就得从题目的某个条件为基础,根据这个条件选择如何能得到局部的最优解。贪心在大多数情况下都是能将题目AC的,但是如果遇到了某种问题,就能在不是完全AC的情况下得到最高的分数,这就是“贪心”策略名字的由来。

解题思路:
   1、看看这题是否适合贪心(如果这道题都不能用贪心的话,那不就等于跳楼吗)
   2、选择贪心的标准(这个是关键)
   3、根据标准把求解的问题分成若干个子问题
   4、对每一个子问题求解,得到子问题的局部最优解
   5、把每个子问题的解局部最优解合成原来问题的一个解

贪心就概念而言是十分抽象的,想要真正了解贪心的精髓就得从具体的例题中获得,不然贪心是很难学会的。

智力大冲浪:

 题意描述(简化版):

    一开始有m元钱,有时间分为n个时段(一个时间段为一个单位时间,又是游戏个数)(n≤500),之间有很多小游戏,每个小游戏都必须在规定期限ti时时间段之前完成(1≤ti≤n)
如果一个游戏没能在规定期限前完成,则要从奖励费m元中扣去一部分钱wi(每个游戏只占一个单位的时间,且只要在规定时段之前完成就不会扣钱),问

分析:按题意可知,既然想赢得最多的钱,那么扣得钱数肯定要最少,那么显然是肯定要根据钱数进行从大到小排序,先把扣的钱数最多的游戏完成。那么这时就会有一个问题,可能会有重复。那么根据这一个问题,我们可以设置一个布尔数组,用来记录当前这个时段有没有被其他的游戏占掉。如果有,那么时段就推前;如果推前的时段又被占了,就继续推前……依次类推,知道找到没有被占用的位置;但是如果之前的时段全部被占用了,那么这个钱就会被扣除。

 那么首先将这个样例进行从大道小排序:

扣除钱数

完成时间段

70

4

60

2

50

4

40

3

30

1

20

4

10

6

 

 

 好,根据这组样例,我们来模拟:

    先完成钱数为70的游戏,然后第4个时间段记为false。

    接下来完成钱数60的游戏,然后第二个时间段即为false、

    然后完成钱数为50的游戏,那么这是时间段4已经被占了,接下来时间推前一格,第3个时间段记为false;

    接着就是40,继续模拟可知3、2都没了,只能占1.

    然后是30,但是通过模拟知道1时间段已经被占了,所以钱数只能被扣除。

    20也被扣除

   10可以完成

那么钱数就是被扣除了50,结果即为9950.

 

那么具体代码如下:

​

#include<bits/stdc++.h>
using namespace std;
	struct qaq{
		long int time;
		long int money;
	}a[501];
bool sort1(qaq x,qaq y){
	return x.money>y.money;
}
int main(){
	long int s,n,m,i,j,k;
	bool f[501]={};
	cin>>s>>n;
	for (i=1;i<=n;i++) cin>>a[i].time;
	for (i=1;i<=n;i++) cin>>a[i].money;
	sort(a+1,a+n+1,sort1);
	for (i=1;i<=n;i++){
	    k=a[i].time;
	    while (f[k]&&k>0) k--;
	    if (k>0) f[k]=1;
	      else s-=a[i].money;
	}
	cout<<s;
	return 0;
}

[点击并拖拽以移动]
​

 

 

修理牛棚:

   题意描述:

   

题目描述

在一个暴风雨的夜晚,农民约翰的牛棚的屋顶、门被吹飞了。 好在许多牛正在度假,所以牛棚没有住满。 有些牛棚里有牛,有些没有。 所有的牛棚有相同的宽度。 自顶遗失以后,农民约翰必须尽快在牛棚之上竖立起新的木板。 他的新木材供应者将会供应他任何他想要的长度,但是供应者只能提供有限数目的木板。 农民约翰想将他购买的木板总长度减到最少。 给出 M(1<= M<=50),可能买到的木板最大的数目;S(1<= S<=200),牛棚的总数;C(1 <= C <=S) 牛棚里牛的数目,和牛所在的牛棚的编号stall_number(1 <= stall_number <= S),计算拦住所有有牛的牛棚所需木板的最小总长度。 输出所需木板的最小总长度作为的答案。

输入格式

第 1 行: M , S 和 C(用空格分开) 第 2 到 C+1行: 每行包含一个整数,表示牛所占的牛棚的编号。

输出格式

单独的一行包含一个整数表示所需木板的最小总长度。

样例数据

input

4 50 18
3
4
6
8
14
15
16
17
21
25
26
27
30
31
40
41
42
43

output

25

数据规模与约定

时间限制:1s1s

空间限制:256MB256MB

注释

[ 一种最优的安排是用板拦住牛棚3-8,14-21,25-31,40-43.]

 

分析:由题意可知,输出的是要最小值,我们得先把牛棚的编号进行排序。先假设一块木板将整个牛棚覆盖,但是题目木板块又是有限的,所以我们一共要把牛棚分成M-1段,显然是再看牛棚之间的间隙,间隙小的先不用管,找出之间间隙前M-1大的进行分区,算出分区长度,再用尾长度到头长度的距离减去分区的间隔即为所求。(每两个木块的间隔为1)

代码如下:

#include<bits/stdc++.h>
using namespace std;
long int i,j,n,m,c,a[201],sum=0,x,b[201];
bool f[201];
int main(){
	cin>>m>>n>>c;
	for (i=1;i<=c;i++) cin>>a[i];
	sort(a+1,a+c+1);
	for (i=1;i<=c-1;i++) b[i]=(a[i+1]-a[i])-1;
	for (i=1;i<=m-1;i++)
	  for (j=i+1;j<=c-1;j++)
	    if (b[i]<b[j]){
	    	x=b[i];b[i]=b[j];b[j]=x;
	    }
	sum=a[c]-a[1]+1;
	for (i=1;i<=m-1;i++) sum-=b[i];
	cout<<sum;
	return 0;
}

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值