zoukankan      html  css  js  c++  java
  • 数据结构 练习 19-活动选择问题的实现(动态规划 和 贪心)

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


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

    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;
    }


    测试结果:

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

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


    再来做个例子吧:

    背包问题:

    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);
     
      
    }
    


    测试:


  • 相关阅读:
    (OK) CORE nodes access Internet—虚拟节点访问互联网—commands
    Open VSwitch—离开VMware的SDN之父Martin Casado是神马大神
    (OK-half) Fedora23——Docker——CORE—testing
    【codeforces 752B】Santa Claus and Keyboard Check
    【codeforces 752C】Santa Claus and Robot
    【codeforces 752E】Santa Claus and Tangerines
    【codeforces 548E】Mike and Foam
    【codeforces 752D】Santa Claus and a Palindrome
    【codeforces 752F】Santa Clauses and a Soccer Championship
    【codeforces 546A】Soldier and Bananas
  • 原文地址:https://www.cnblogs.com/snake-hand/p/3159737.html
Copyright © 2011-2022 走看看