(1)活动安排问题
设有n个活动的集合E={1, 2, …, n},其中每个活动都要求使用同一资源,而在同一时间内只有一个活动能使用这一资源。每个活动i都有一个要求使用该资源的起始时间si和一个结束时间fi,且si <fi 。如果选择了活动i,则它在半开时间区间[si, fi)内占用资源。若区间[si, fi)与区间[sj, fj)不相交,则称活动i与活动j是相容的。 随机生成n个任务(n=8,16,32…),用贪心法求解,做出图像,横坐标为活动个数,纵坐标为执行时间。并简要分析你设计的贪心法是否一定得到最优解。
代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<time.h>
#define x first
#define y second
using namespace std;
const int N = 1e7 + 10;
struct Lists
{
int a,b;
bool operator < (const Lists& w) const
{
return b < w.b;
}
}st[N];
int main()
{
int n = 1;
while( n < 1e7)
{
for(int i = 0 ; i < n ; i ++ )
{
int a = rand() % 1000;
int b = rand() % 1000;
if(a >= b ) b += a;
st[i] = {a,b};
}
sort(st,st+n);
int ans = 1;
int ends = st[0].b;
clock_t cstart,cends;
cstart = clock();
for(int i = 1; i < n ; i ++ )
{
if(st[i].a >= ends)
{
ends = st[i].b;
ans++;
}
else continue;
}
cends = clock();
if(n <= 1024 )
for(int i = 0; i < n ; i ++ )
{
cout<<"(a = "<<st[i].a <<" b = " << st[i].b <<") ";
if(i%3==0 && i != 0) cout << endl;
}
cout << endl;
cout << "数据规模是 "<< n<< " 结果是 :" << ans <<endl;
cout << "运行时间是 "<< cends - cstart<<endl;
n*=2;
}
return 0;
运行结果
算法说明
算法描述:
输入完数据后,按照活动结束时间进行排序,先结束的排在前。
1.选取结束时间最早的活动。
2.比较当前活动结束时间与下一个活动开始时间
2.1当前结束时间小于等于下一个活动开始时间,则选取下一个活动
2.2淘汰下一个活动,访问下下个活动
通过暴力枚举,可以验证这样确实是最优的
(2)线段覆盖
问题描述:在一维空间中随机生成N(N=8,16,32…)条线段的起始坐标与终止坐标,要求求出这些线段一共覆盖了多大的长度(重叠区域只算一次)。分析算法的时间复杂度,画出算法的执行时间随N变化的曲线图。
代码
#include<iostream>
#include<cstring>
#include<algorithm>
#include<time.h>
using namespace std;
const int N = 1e7;
struct Lists
{
int a,b;
bool operator < (const Lists& w) const
{
return a < w.a;
}
}st[N];
int n;
int main()
{
n = 1;
while( n < 1e7)
{
int pt[n+1];
int idx = 0;
for(int i = 0 ; i < n ; i ++ )
{
int a = rand() % 1000;
int b = rand() % 1000;
if(a >= b ) b += a;
st[i] = {a,b};
}
clock_t cstart,cends;
cstart = clock();
sort(st,st+n);
int ans = st[0].b - st[0].a + 1;
int ends = st[0].b;
for(int i = 1; i < n ; i ++ )
{
if(st[i].a > ends)
{
ends = st[i].b;
pt[idx++] = ans;
ans = st[i].b - st[i].a +1;
}
else if(st[i].a <= st[i-1].b)
{
if(st[i].b <= st[i-1].b) continue;
else
{
ans+=st[i].b - ends;
ends = st[i].b;
}
}
}
cends = clock();
if(n <= 1024 )
for(int i = 0; i < n ; i ++ )
{
cout<<"(a = "<<st[i].a <<" b = " << st[i].b <<") ";
if(i%3==0 && i != 0) cout << endl;
}
cout << endl;
for(int i = 0; i < idx; i ++ ) ans = max(ans,pt[i]);
cout << "数据规模是 "<< n << " 长度是 :" << ans <<endl;
cout << "运行时间是 "<< cends - cstart<<endl;
n*=2;
}
return 0;
}
运行结果
时间复杂度分析
时间复杂度分析:
输入数据 最少时间花费:n 最大时间花费:4n
排序 最少时间花费:nlogn 最大时间花费:n^2(极少出现)
计算结果 时间花费:3n - 3
所以总的时间复杂度的量级为 nlogn