贪心之区间调度

23 篇文章 0 订阅
22 篇文章 0 订阅

贪心之区间调度

单区间调度

**问题定义::**存在单一资源,有一组时间区间形式表示的资源使用请求S={S1,S2,S3…Sn}.某一个请求需要使用资源一段时间,并且有开始时间begin 结束时间end。如果两个请求没有时间重复可以,分配到一起,否者不可以。求 在时间内,最多能玩成的请求个数?
例如: 有一间多媒体课室,某一个周末有多个社团想要申请这间课室去举办社团活动,每个社团都有一个对应的申请时间段,比如周六上午8:00-10:00。求出这间课室在这个周末最多能满足几个社团的需求。
解题思路:: 利用贪心算法,选最早结束的活动,保证资源被早时间释放,越早结束剩余的时间越多,安排的社团也就越多。实现整体安排最大化。

伪代码::

 初始化 S 是所有需求的集合,A 为空集                        
 对 S 中的需求 Si,根据结束时间早晚排序从早到晚(结束时间) 
    for Ri int R,do                                          
       if Ri与 A 的请求可以共容                          
           A=A并R;                                           
	      endif                                               
	  endif                                                      
	  return A      

C++代码::
copy的
vector+ 结构体;

#include <iostream>
#include <bits/stdc++.h>
#include <vector>
using namespace std;
const int maxn=100;
struct S { // 感觉用pair更方便
    int begin,end;
} s[maxn];
bool operator<(const S& s1,const S& s2)
{
    return s1.end<s2.end;
}
vector<S> ve;
int main()
{
    int S_num;
    cin>>S_num;
    for(int i=0; i<S_num; i++) {
        cin>>s[i].begin>>s[i].end;
    }
    cout<<endl;
    sort(s,s+S_num);
    ve.push_back(s[0]);
    for(int i=1;i<S_num;i++)
    {
    	if(ve[ve.size()-1].end<=s[i].begin)
    	ve.push_back(s[i]);
	}
	cout<<ve.size()<<endl;
    return 0;
}

仿写
vector+pair

#include <bits/stdc++.h>
using namespace std;
pair<int,int> p[99];
bool cmp(pair<int,int> p1, pair<int ,int> p2)
{
    return p1.second<p2.second;
}
int main()
{
    int c;
    cin>>c;
    for(int i=0; i<c; i++)
        cin>>p[i].first>>p[i].second;
    cout<<endl;
    sort(p,p+c,cmp);
    vector<pair<int,int> > ve;
    ve.push_back(p[0]);
    for(int i=0; i<c; i++)
        if(ve[ve.size()-1].second<= p[i].first)
            ve.push_back(p[i]);
    cout<<ve.size()<<endl;
    return 0;
}

多区间调度问题

问题定义:: 有多个或者无限个相同的资源可以使用 ,有一组以时间形式表示的资源请求R={R1,R2,R3…Rn}; 某个请求想占用资源一段时间,时间开始于begin(i)结束于end(i), 如果连个请求,时间上没有重叠,两请求可以同时存在 ,如何用最少的资源,来满足所有的请求,——也就是做到资源浪费最小化。
例子:: 很多间课室,某个周末有多个社团需要申请课室办活动,每个社团都有一个 对应的申请时间,求最少需要多少间课室才能够满足所有社团的需求.(很多间教室——>多个资源、周末——>时间一定,在固定的一段时间)《 多区间调度问题:Ps: 也就是多个资源分配。
解题思路:: 贪心算法,将需求按照开始时间的早晚进行排序,然后开始为这些资源打标签,每个标签代表都一个资源,需求req-i被打上标签k表示该请求分配到的资源是k。遍历排序后的需求,如果一个需求与某个已分配资源上的其他安排不冲突,则把该需求也放进该资源的安排考虑中;如果冲突,那么应该要给此需求分配新的资源,已用资源数量加一。
伪代码::

  对n个需求按照开始时间从早到晚排序
   假设排序后需求为R={R1,R2,R3..Rn};
   初始化tagsize=1;
   for  i=1 to n  do:
      tags={1,2,3...tagsize};
      for j=1  to  i-1  do
	     if (Rj与Ri时间区间重叠产生冲突)
		    tags=tags-{Rj的标签};
		 endif
       endfor
       if(tags为空集)
	   tagsize=tagsize+1
	   将tagsize贴在Ri上
	 endif
	 else
	    在tags剩下的标签中随便挑一张贴个Ri
		endelse
  endfor
   这个时候每个请求上都有标签,每个标签对应其申请资源编号,
   此时tagsize就至少需要的资源量
   return tagsize;

C++ 代码::

#include<bits/stdc++.h>
using namespace std;
struct R {
    int b,e,t;
} r[99];
bool operator<(const R&r1,const R&r2)
{
    return r1.b<r2.b;//  按时间的开始先后顺序排列
}
int main()
{
    int R_mum;
    cin>>R_mum;
    for(int i=0; i<R_mum; i++)   // 录入开始和结束时间
        cin>>r[i].b>>r[i].e;
    sort(r,r+R_mum);           // 排序
    int tagsize=1;            // 使用的资源数量
    r[0].t=0;
    bool ts[99];
    for(int i=1; i<R_mum; i++) {
        memset(ts,true,sizeof(ts));
        for(int j=0; j<i; j++) {
            if(r[j].e>r[i].b) {   //开始时间小于结束时间,活动冲突
                ts[r[j].t]=false;//将符合的活动都设为未标记过
            }
        }
        bool just=true;
        int tg;// 0-> tagsize 是否存在着没有安的活动
        for(int j=0; j<tagsize; j++) {
            if(ts[j]) {
                just=false;  // 标记没安排的活动
                tg=j; //有则  取出其下标
                break;
            }
        }
        if(just) {// 没有活动能在0-> tasize剩下的活动,只能在占用一个资源
            r[i].t=tagsize; // 给某个活动打上在那个资源上开展的标签
            ++tagsize;// 占用资源加1
        } else //如果可以安排这个活动,就把相应的标签贴给这个活动
            r[i].t=tg;
    }
    cout<<tagsize<<endl;
    return 0;
}
// 看的稀里糊涂的  ^_^
// 加油!!

最小延迟调度

问题定义:: 存在单一资源和一组使用资源请求R={R1,R2,R3…Rn};与1,2不同这里的资源从0时刻开始有效(开始接受申请,开始被使用),每一个请求都有个借宿时间end,每个请求都要占用资源一段连续时间占用时间为time。每个请求都希望在end之前完成(单一资源同一时刻只能完成一个请求) 如果我们想完成每个请求,也可以让某些请求有延迟,(也就是在end后才能完成,可以拖延时间,让我们确定一个合理的安排,让所有请求延迟时间中的最大值,是所有可能时间安排最小的。 从时刻0开始,为每个请求req-i分配一个长度time(i)的时间区间,把区间标记为[begin(i), end(i)],其中end(i) = begin(i) + time(i)。如果end(i) > ddl(i),则请求req-i被延迟,延迟时间为delay(i) = end(i) - ddl(i);否则delay(i) = 0。合理安排需求,使得maxDelay = max{delay(1), delay(2), …, delay(n)}是所有可能的安排中最小的。
解题思路:: 心算法 按照时间截止时间ddl 排序,越早截止的任务越早完成,该算法是一个没有空闲 的最优调度 。从时刻0开始处理,知道最后一个请求执行完,释放资源才空闲。
伪代码::

  将需求按照截止时间进行排序
*  假设排序后截止时间为 ddl[1]<=...<=ddl[n];
*  start=0;
*  maxdelay=0;
*  for i to n ,do:
*    begin [i]=start;
*    end[i]=start+time[i];
*    start=start+time[i]
*    if  maxdelay <end[i]-ddl[i]
*       l=end[i]-ddl[i];
*     endif
*   endfor
* return maxdelay;

C++\代码::

#include <bits/stdc++.h>
using namespace std;
struct R {
    int time,ddl;//占用资源时长和 给姐素的时间
    int begin,end;  //开始和结束的时间
} r[99];
bool operator<(const R& r1,const R& r2)
{
    return r1.ddl<r2.ddl;// 按照结束时间排序
}
int main()
{
    int  R_mum;
    cin>>R_mum;
    for(int i=0; i<R_mum; i++)
        cin>>r[i].time>>r[i].ddl;// 录入
    sort(r,r+R_mum);  // sort
//    cout<<endl;  // 显示验证程序的问题
//    for(int i=0;i<R_mum;i++)
//    cout<<r[i].time<<" "<<r[i].ddl<<endl;
//    cout<<endl;
    int maxdelay=0;// 定义最大的延误时间
    int start=0; //从0开始处理请求
    for(int i=0; i<R_mum; i++) { //板子
        r[i].begin=start;  //最开始的时间给begin,自我感觉,没啥用
        r[i].end=start+r[i].time;//  end 有一点用吧,但是也不用再结构体里定义啊
        start=start+r[i].time;// 循环累加时间,每次找到该活动的最早开始时间,也没啥用
        if(maxdelay<r[i].end-r[i].ddl)//找出结束时间和当前时间的差最小值,也就是答案
            maxdelay=r[i].end-r[i].ddl;
    }
//	cout<<start<<endl; // 最后的总时间
    cout<<maxdelay<<endl;   //最先最大延误时间
    return 0;
}

感觉好多没用的地方,写个新的吧。

#include<bits/stdc++.h>
using namespace std;
bool cmp(pair<int,int> p1,pair<int ,int> p2)
{
    return p1.first<p2.first;
}
pair<int,int> p[99];
int main()
{
    int R_mum;
    cin>>R_mum;
    for(int i=0; i<R_mum; i++)
        cin>>p[i].first>>p[i].second;
    sort(p,p+R_mum,cmp);
    cout<<endl;
    for(int i=0; i<R_mum; i++) //验证是否排序成功
        cout<<p[i].first<<" "<<p[i].second<<endl;

    int start=0,maxdelay=0;
    for(int i=0; i<R_mum; i++) {
        int end=start+p[i].first;
        start=start+p[i].first;
        if(maxdelay<end-p[i].second)
            maxdelay=end-p[i].second;
    }
    cout<<maxdelay<<endl;
    return 0;
}

!^_^ 加油!!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值