数据结构 练习 19-活动选择问题的实现(动态规划 和 贪心)

摘要:
现在要进行一些列如下活动,注意每个时间段只能进行一场活动,也就是活动不能同时进行,要求举行的活动次数最多。老规矩,动态规划,要找出两个问题:1,子问题的最优解;2,子问题是什么。本想用动态规划试试做做,操蛋的做不出来,算了还是贪心吧,毕竟贪心最简单对于活动调度,不过有个证明过程。

问题叙述:如下图表示活动的开始和结束时间,s[i],开始时间;f[j]结束时间。现在要进行一些列如下活动,注意每个时间段只能进行一场活动,也就是活动不能同时进行,要求举行的活动次数最多。求调度方法。

数据结构 练习 19-活动选择问题的实现(动态规划 和 贪心)第1张

老规矩,动态规划,要找出两个问题:

1,子问题的最优解;

2,子问题是什么。

abviously,本问题的最优解为:活动数的次数最多,子问题是:看递推公式

设c[i]为第i个 位置处的活动次数.......做不出来了,以后补充。

本想用动态规划试试做做,操蛋的做不出来,算了还是贪心吧,毕竟贪心最简单对于活动调度,不过有个证明过程。先上代码吧。

#include<iostream>
using namespace std;
//s 活动开始时间的数组,f活动结束时间的数组,n 数组的大小;
const int N=11;
void GreedySelector(int* s,int* f,int n )
{
  bool A[N];
  A[0]=true;
  int j=0;
  for(int i=1;i<N;++i)
  {
  if(s[i]>f[j])
  {
	  A[i]=true;
	  j=i;
  }
  else
  {
  A[i]=false;
  }
  }
for(int k=0;k<N;++k)
  {
   if(A[k]==true)
	   cout<<k<<" ";
  }
}
int main()
{
int s[N]={1,3,0,5,3,5,6,8,8,2,12};//活动的开始时间
int f[N]={4,5,6,7,8,9,10,11,12,13,14};//活动的结束时间
 GreedySelector( s, f, N );
return 0;
}

测试结果:

数据结构 练习 19-活动选择问题的实现(动态规划 和 贪心)第2张

证明略,没怎么明白,智商啊,亵渎了 我的大脑袋。

把算法导论的证明贴出来吧:

数据结构 练习 19-活动选择问题的实现(动态规划 和 贪心)第3张

再来做个例子吧:

背包问题:

0-1背包问题:有一个窃贼在一家商店时发现有n件物品,第i件物品值vi元,重wi磅。此处,vi,wi都是整数,。他希望带走的东西越值钱越好,但他的背包中至多只能装下W磅。

,W为一整数。应该带走那几样东西呢?(0-1的意思是:物品或被带走,或被留下,不能带走一部分,留下一部分)

部分背包问题:场景与上面类似,但是窃贼可以带走物品的一部分,而不必做出0-1的二分选择。

下面一个个来解决吧。

0-1:

这里讲解的不错:http://blog.csdn.net/lcj_cjfykx/article/details/8852465

我自己参照写的代码:

#include<iostream>
using namespace std;
//w 物品的重量,v物品的价值,count物品的数量,m是背包最大的容量
void processing(int* w,int* v,int count,int m,int(* c)[11])
{
	for(int i=1;i<=count;++i)
		for(int j=1;j<=m;++j)
		{
		 if(w[i]<=j)//可以放对应的背包了
		 {
		  if(c[i-1][j]>c[i-1][j-w[i]]+v[i])
			  c[i][j]=c[i-1][j];
		  else
			  c[i][j]=c[i-1][j-w[i]]+v[i];
		 }
		 else
		 {
		  c[i][j]=c[i-1][j];
		 }		
		}
}
void Printf(int count,int m,int (*c)[11],int* log,int *w)
{
     int j=m;
	 for(int i=count;i>=1;--i)
        if(c[i][j]==c[i-1][j])
            log[i]=0;
		else
		{
		log[i]=1;
		j=j-w[i];
		}
}
int main()
{
	int w[4]={0,3,4,5};
	int v[4]={0,4,5,6};
    int c[4][11];
    int log[4];
	int count=3;
	int m=10;
	for(int i=0;i<=3;++i)
		for(int j=0;j<=10;++j)
			c[i][j]=0;
    processing(w, v,3,10,c);
    Printf(3,10,c,log,w);
	cout<<"装入的物品为:";
	for(int i=1;i<=count;++i)
		if(log[i]==1)cout<<i<<" ";
	cout<<"总价值为:"<<c[count][m];
}

部分背包问题:

上代码

#include<iostream>
using namespace std;
const int n=10;
//定义一个结构体
typedef struct goods
{
	int w;//物品的重量
	int v;//物品的价值
	double VbyW;
} goods;
struct selectedGood
{
   int num;//选择的商品号
   int residue;//最后一种商品被选择的数量,因为部分选取
};
void fastSort(goods * inputData,int n,int startLoc);
void backBag(goods* igoods,int n,int m,selectedGood* SG);
int main()
{   
	int W[n]={12,3,5,6,3,43,56,2,65,43};
	int V[n]={4,1,7,4,65,32,4,8,3,7};
    int m=30;
    selectedGood SG;
	//初始化
	SG.num=-1;
	SG.residue=0;
	selectedGood* pSG=&SG;
	goods igoods[n];
	for(int i=0;i<n;++i)
		igoods[i].w=W[i];
	for(int j=0;j<n;++j)
		igoods[j].v=V[j];
    for(int k=0;k<n;++k)
		igoods[k].VbyW=(double)igoods[k].v/igoods[k].w;
    fastSort(igoods,n,0);//对单位重量的价值进行排序
    backBag( igoods, n, m,pSG);
	cout<<"放入背包的物品:"<<endl;
	int k;
	for( k=0;k<pSG->num;++k)
	{
		cout<<igoods[k].w<<"  ";
	}
	if(pSG->residue!=0)
		cout<<"最后一个物品"<< igoods[pSG->num-1].w<<"只取"<< pSG->residue;
    return 0;
}
void backBag(goods* igoods,int n,int m,selectedGood* SG)
{ 
	int tmp=0;
	int residue=0;
    int i;
	for( i=0;i<n;++i)
	{
		//tmp+=igoods[i].w;
		if(tmp+igoods[i].w<=m)
		{
			tmp+=igoods[i].w;
		}
		else
		{
	    SG->residue=m-tmp;
		SG->num=i+1;
		break;
		}
	}
    if(i==n)
	{   
		SG->num=i+1;
	}           
}
void fastSort(goods * inputData,int n,int startLoc)
{
  if(n<2) return ;//递归停止的条件
  int i=startLoc-1;//指向最后一个小于基元的数据
  int j=startLoc;//移动j,挨个遍历元素
  double baseDa=inputData[startLoc+n-1].VbyW;//获取基元
  goods tmp;
  int k=0;
  while(j<=startLoc+n-1)
  {
	  if(inputData[j].VbyW>inputData[startLoc+n-1].VbyW||j==startLoc+n-1)
     {
      i++;
	  k++;
	  //交换
	  tmp=inputData[j];
	  inputData[j]=inputData[i];
	  inputData[i]=tmp;
     }
    j++;
    }
  startLoc=i-k+1;//左边分组的位置,右边分组的位置为:i+1
  fastSort(inputData,i-startLoc,startLoc);
  fastSort(inputData,n-(i-startLoc)-1,i+1);
}

测试:

数据结构 练习 19-活动选择问题的实现(动态规划 和 贪心)第4张

免责声明:文章转载自《数据结构 练习 19-活动选择问题的实现(动态规划 和 贪心)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇《开发板 —— i2c-tools调试i2c设备》Go -- LFU类(缓存淘汰算法)(转)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

A Mini Locomotive(动态规划 01)

 /*  题意:选出3个连续的 数的个数  为K的区间,使他们的和最大 分析: dp[j][i]=max(dp[j-k][i-1]+value[j],dp[j-1][i]);   dp[j][i]:从j个数种选出i个连续区间  数值的最大和 value[j]:第j个区间内的数的和 和背包有点像,但要活用   */   #include <cstdio...

Redis 如何存储上亿级别的用户状态?

作者:铂赛东链接:https://www.jianshu.com/p/ee79ae681b74 1 前段时间,在网上看到一道面试题: 如何用redis存储统计1亿用户一年的登陆情况,并快速检索任意时间窗口内的活跃用户数量。 觉得很有意思,就仔细想了下 。并做了一系列实验,自己模拟了下 。还是有点收获的,现整理下来。和大家一起分享。 Redis是一个内存数...

Linux内核数据结构映射-idr(转)

原文:https://blog.csdn.net/m0_37128231/article/details/96727068?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task 参考链接: linux idr机制...

漫谈软件系统中的形式结构

温故而知新。 引子 软件系统的功能是与数据打交道。包括:数据的采集、解析、传输、组织、存储、转换、展示。其逻辑单元是加法、复制与传输。软件的功能简单明了,是数据使用场景赋予了实际的意义。 软件系统的难点在于其形式结构的复杂性。软件的主要形式元素有:数据和指令。其形式结构主要有:数据与数据组合的数据结构、数据与指令结合的指令集、指令与指令组合的控制结构。 本...

将json转换为数据结构体

主要用到的依赖:(划重点:这个依赖需要加jdk版本号,不加的话用不了,且目前最高是jdk15) (ps: 用于json与其他类型格式转换,JSONObject, JSONArray等来自这个包) <!-- https://mvnrepository.com/artifact/net.sf.json-lib/json-lib -->...

linux内核之文件系统

本文主要是基于百度文库的《Linux2.4.30内核文件系统学习(多图).doc》和360doc的《Linux内核虚拟文件系统》修改而来,当然还参考了其他的一些文档,在此就不一一列出了。本来在看到这些文章后,都没有勇气再写点文件系统方面的东西了,这些文章实在太精彩了。最后还是鼓足勇气决定把整理的资料增加了一点自己的理解写下来,主要目的是让各位高手看看我的理...