贪心算法(上)

今天我写写贪心算法(上),主要写写一些题目和方法。


很高兴的借(fu)鉴(zhi)、选(kao)取(bei)了一些。

贪心算法的定义:

贪心算法是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,只做出在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。

解题的一般步骤是:

1.建立数学模型来描述问题;

2.把求解的问题分成若干个子问题;

3.对每一子问题求解,得到子问题的局部最优解;

4.把子问题的局部最优解合成原来问题的一个解。

此外,贪心常用sort排序,来取一些最大值。

当然,不是猜完就能用的,一定要证明[哈哈]。


常用题目:①背包问题,其实属于dp动态规划。

                  ②活动安排问题,按结尾从小到大排序,尽量挑开始符合结束时间的。


题目:1319:【例6.1】排队接水

题目缩略:

有n个人在一个水龙头前排队接水,假如每个人接水的时间为Ti,请编程找出这n个人排队的一种顺序,使得n个人的平均等待时间最小。

思路:简单的数学问题。最快的最先来接水,先排序,后面一个一个来。

代码:

#include <bits/stdc++.h>

using namespace std;

struct nbdj

{

  int num,t;

} a[10005];

int n,ts,m;

double ans;

bool cmp(nbdj a,nbdj b)

{

  if(a.t!= b.t)return a.t<b.t;

  return a.num<b.num;

}

int main()

{

  cin>>n;

  m=n;

  for(int i=1; i<=n; i++)

  {

    cin>>a[i].t;

    a[i].num=i;

  }

  sort(a+1,a+n+1,cmp);

  for(int i=1; i<=n; i++)

  {

    cout<<a[i].num<<" ";

    ts+=a[i].t*(n-i);

  }

  ans=ts*1.0/n;

  printf("\n%.2lf\n",ans);

  return 0;

}


题目:1320:【例6.2】均分纸牌(Noip2002)、

题目:

有n堆纸牌,编号分别为 1,2,…, n。每堆上有若干张,但纸牌总数必为n的倍数。可以在任一堆上取若干张纸牌,然后移动。

移牌规则为:在编号为1的堆上取的纸牌,只能移到编号为 2 的堆上;在编号为 n 的堆上取的纸牌,只能移到编号为n-1的堆上;其他堆上取的纸牌,可以移到相邻左边或右边的堆上。

现在要求找出一种移动方法,用最少的移动次数使每堆上纸牌数都一样多。

例如 n=4,4堆纸牌数分别为:  ① 9 ② 8 ③ 17 ④ 6

移动3次可达到目的:

从 ③ 取4张牌放到④(9 8 13 10)->从③取3张牌放到 ②(9 11 10 10)-> 从②取1张牌放到①(10 10 10 10)。

思路:从左到右,如果缺,从右边要,如果多,给右边

代码:

#include <bits/stdc++.h>

using namespace std;

int a[250],n,ans,num;

int main()

{

  cin>>n;

  for(int i=1; i<=n; i++)

  {

    cin>>a[i];

    num+=a[i];

  }

  num/=n;

  for(int i=1; i<=n; i++)

  {

    a[i]-=num;

  }

  int i=1;

  while(a[i]==0&&i<=n) i++;

  while(i<=n)

  {

    if(a[i]!=0)

    {

      a[i+1]+=a[i];

      ans++;

    }

    i++;

  }

  cout<<ans<<endl;

  return 0;

}


好勒,今天就写到这,明天再写,日更完成。明天似乎有4到贪心题要写。不过也没事,都做好了,明天见。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容