算法模板-贪心算法

活动选择

假定一个有n个活动(activity)的集合S={a1,a2,…,an},这些活动使用同一个资源(例如同一个阶梯教室),而这个资源在某个时刻只能供一个活动使用。每个活动ai都有一个开始时间si和一个结束时间fi,其中0<=si<fi<正无穷。如果被选中,任务ai发生在半开时间区间[si,fi)期间。如果两个活动ai和aj满足[si,fi)和[sj,fj)不重叠,则称它们是兼容的。也就说,若si>=fj或sj>=fi,则ai和aj是兼容的。在活动选择问题中,我们希望选出一个最大兼容活动集。假定活动已按结束时间fi的单调递增顺序排序


#include<cstdio>
#include<iostream>
#include<cstring>
#include<climits>
using namespace std;
#define maxsize 1000
typedef long long ll;
int s[maxsize],f[maxsize],a[maxsize],n;
void init()
{
 for(int i=1;i<=n;i++)
  scanf("%d",&s[i]);
 for(int i=1;i<=n;i++)
  scanf("%d",&f[i]);
 memset(a,0,sizeof(a));
}
void greed()
{
 int cnt=0;
 a[cnt++]=1;
 k=1;
 for(int m=2;m<=n;m++)
 {
  if(s[m]>=f[k])
  {
   a[cnt++]=m;
   k=m;
  }
 }
}
void print()
{
 for(int i=0;a[i]!='\0';i++)
  printf("a%d",a[i]);
 printf("\n");
}
int main()
{
 while(~scanf("%d",&n))
 {
  init();
  greed();
  print();
 }
 } 

分数背包

分数背包与01背包问题不同点就是如果某物品无法被全部放入可以放入一部分
思路还是降序排列然后往背包添加
题目:
有 m 元钱,n 种物品;每种物品有 w 磅,总价值 v 元,

#include<iostream>
#include<queue>
#include<vector>
using namespace std;
struct pack
{
 double w;
 double v;
 int num;
 bool operator<(const pack &a)const{
  return (v/w)<(a.v/a.w);//最大值优先; 
 }
};
priority_queue<pack>q;
#define N 1000
int n;
double m,x[N];
double knapsack()
{
 double sum=0;
 for(int i=1;i<=n;i++) x[i]=0;
 int i;
 while(q.size()>0)
 {
  pack t=q.top();
  if(t.w>m) break;
  q.pop();
  x[t.num]=1;
  m-=t.w;
  sum+=t.v;
 }
 if(q.size()!=0)
 {
  pack t=q.top();
  q.pop();
  x[t.num]=m/t.w;
  sum+=t.v*x[t.num];
 }
 return sum;
 } 
int main()
{
 scanf("%lf%d",&m,&n);
 for(int i=1;i<=n;i++)
 {
  pack a;
  scanf("%d%lf%lf",&a.num,&a.w,&a.v);
  q.push(a);
 }
 double sum=knapsack();
 printf("%lf",sum);
}

一个小注意

 bool operator<(const pack &a)const{
  return (v/w)<(a.v/a.w);//最大值优先; 
 }
}

这一部分return返回的总是a的值,这只能对于优先队列的排列

对于sort函数algorithm

#include<algorithm>//sort函数包含的头文件
typedef struct student
{
    string name;           //学生姓名
    int achievement;     //学生成绩
} student;
//这是函数是sort函数的第三个参数
//如果希望升序排序,就是"<",降序排列就是">"号
//如果希望用其他的参数作为排序条件,只需要把相应的条件改一下(如果改成name),这样结构体就以name作为排序标准
bool comparison(student a,student b){
    return a.achievement<b.achievement;
}//成立返回前面
sort(sort(stu,stu+n,comparison);

区间着色问题

假设要用很多个教室对一组活动进行调度。我们希望使用尽可能少的教室来调度所有的活动。请给出一个有效的贪心算法,来确定哪一个活动应使用哪一个教室。
(这个问题也被成为区间图着色(interval-graph coloring)问题。我们可作出一个区间图,其顶点为已知的活动,其边连接着不兼容的活动。为使任两个相邻结点的颜色均不相同,所需的最少颜色对应于找出调度给定的所有活动所需的最少教室数。)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
# define N 100
typedef struct A
{
 int number;            //活动编号
 int begin;           //活动开始时间
 int end;            //活动结束时间
 bool flag;          //此活动是否被选择
 int roomnum;      //此活动在哪间教室举行
}Activity;
bool cmp(Activity a,Activity b)
{
    return a.end<b.end;
}
int select_room(Activity *a, int *time, int n)
{
 int i = 1, j = 1;
 //下面初始化数据,把第一个活动安排了,然后循环从第二个活动开始
 int sumroom=1;        //已经占用的教室,计算然后返回最终值
 int sumact=1;           //已经被选择的活动,初始化为1
 time[1] = a[0].end;      //初始化教室1的最后一个活动的结束时间为活动1的结束时间
 a[0].roomnum = 1;         //将第一个活动占用的教室初始化为教室1
 for (i = 1; i < n; i++)                   //遍历i个活动
 { 
   for(j=1;j<=sumroom;j++)                    //遍历j个教室,把活动i放进哪个教室
   if (a[i].begin >= time[j] && (!a[i].flag))          //活动i开始的时间比教室j最后一个活动的结束时间晚,且活动i没有被规划过。那么就应该吧活动i划入教室j
   {                                                   //进行一波更新
    a[i].roomnum = j;
    a[i].flag = true;
    time[j] = a[i].end;
    sumact++;
   }
   if (sumact < n&&i == n - 1)             //已经把一间教室能加入的活动搞完了,活动i不能已有加入教室,那么它就自己新开一间教室
   {
    i = 0;                              //控制重新遍历的条件
    sumroom++;
   }
 }
 return sumroom;
}
int main()
{
 Activity a[N];          //定义一个结构体
 int time[N];            //time 用于记录某个教室里面末尾活动的结束时间,方便与下一个活动的开始时间比较
 int n,i=0,j;                  //输入的活动个数
 int sum;
 int k = 0;
 scanf("%d", &n);
 for (i = 0; i < n; i++)
 {
  time[i + 1] = 0;
  a[i].number = i + 1;
  a[i].flag = false;
  a[i].roomnum = 0;      
  scanf("%d", &a[i].begin);
  scanf("%d", &a[i].end);
 }
 sort(a,a+n,cmp);
 sum=select_room(a,time,n);
 printf("%d\n",sum);
 for (i = 0; i < n; i++)
  printf("%d->%d\n",a[i].number,a[i].roomnum);
}

huffman切割木板

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
priority_queue<int,vector<int>, greater<int> > q;
int n,t,a,b;
long long  sum=0;
int main()
{
 scanf("%d",&n);
 for(int i=0;i<n;i++)
 {
  scanf("%d",&t);
  q.push(t);
 }
 if(q.size()==1)
 {
  sum+=q.top();
  q.pop();
 }
 while(q.size()>1)
 {
  a=q.top();
  q.pop();
  b=q.top();
  q.pop();
  sum+=(a+b);
  q.push(sum);
 }
 printf("%lld",sum);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值