提问排课问题和寻找方案的源程序!!

img

怎样寻找下一次方案 已经用0/1输出了课表
急需解答!有没有懂的人能详细说明一下 谢谢!

img

img

  • 你可以参考下这个问题的回答, 看看是否对你有帮助, 链接: https://ask.csdn.net/questions/7559369
  • 这篇博客也不错, 你可以看下统计0/1字符串中0和1连续出现的额最大次数
  • 除此之外, 这篇博客: 蛮力法与动态规划法求解0/1背包问题中的 蛮力法与动态规划法求解0/1背包问题 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 蛮力法(我用的是穷举2的n方个可能选择)

    #include<iostream>
    #include <math.h>
    #include <windows.h>
    #include<iomanip>
    #define N 100
    using namespace std;
    
    void conversion(int n,int b[]){
    	int i;
    	for(i=0;i<N;i++){
    	b[i] = n%2;
    	n = n/2;
    	if(n==0)
    		break;
    	}
    }
    
    int *BagProblem(int w[],int v[],int C,int len){
    	int maxValue = 0;
    	int b[N];
    	int *temp;//temp就是解
    	temp = (int *)malloc(sizeof(int)*len); 
    	int value,weight,i,j;
    	
    	//穷举2的n方个可能的选择 
    	for(i=0;i<pow(2,len);i++){
    		//初始化数组b为0 
    		for(j=0;j<len;j++){
    			b[j] = 0;
    		}
    		//转化 
    		conversion(i,b);
    		value = 0;
    		weight = 0;
    		for(j=0;j<len;j++){
    			weight += w[j]*b[j];
    			value += v[j]*b[j];
    		}
    		//如果当前的子集满足此两个条件,则为目前最优 
    		if(weight<=C&&maxValue<value){
    			maxValue = value;
    			//将temp重置 
    			for(j=0;j<len;j++){
    				temp[j]=0;
    			}
    			//将当前的b[j]复制到temp保存 
    			for(j=0;j<len;j++){
    				temp[j]=b[j];
    			}
    		} 
    	}
    	//循环完毕,返回结果子集
    	return temp;
    }
    
    int main(){
    	int w[]={2,2,6,5,4};
    	int v[]={6,3,5,4,6};
    	int C = 10,value = 0;
    	int len = 5,i;
    	
    	//求时间花费 
    	LARGE_INTEGER nFreq;
        LARGE_INTEGER nBeginTime;
        LARGE_INTEGER nEndTime;
        double time;
    	QueryPerformanceFrequency(&nFreq);
    	QueryPerformanceCounter(&nBeginTime);
    	//计时代码区间
    	 
    	int *result = BagProblem(w,v,C,len);
    	
    	QueryPerformanceCounter(&nEndTime);
    	time=(double)(nEndTime.QuadPart-nBeginTime.QuadPart)*1000000000/(double)(nFreq.QuadPart);
    	//不计时代码区间 
    	for(i=0;i<len;i++){
    		if(result[i]==0)
    			continue;
    		else
    			cout<<i+1<<" ";//输出所选物品的序号 
    	}
    	cout<<endl;
    	for(i=0;i<len;i++){
    		value += v[i]*result[i];
    	}
    	cout<<"取得的最大价值为:"<<value<<endl;
        cout  << time; //单位是纳秒.
    	
    	return 0;
    }
    

    动态规划法

    #include<iostream>
    #include <windows.h>
    #include<iomanip>
    using namespace std;
    
    //动态规划法求解0/1背包问题,实质是一个填表的过程 
    int *KnapSack(int w[],int v[],int n,int C){
    	int V[n+1][C+1];
    	int *x;
    	x = (int *)malloc(sizeof(int)*(n-1));
    	int i,j;
    	//初始化第0列 
    	for(i=0;i<=n;i++)
    		V[i][0] = 0;
    	//初始化第0行 
    	for(j=0;j<=C;j++)
    		V[0][j] = 0;
    	//计算第i行,进行第i次迭代
    	for(i=1;i<=n;i++)
    		for(j=1;j<=C;j++)
    			if(j<w[i])
    				V[i][j] = V[i-1][j];
    			else
    				V[i][j] = max(V[i-1][j],V[i-1][j-w[i]]+v[i]);
    	//求放入背包的物品 
    	for(j=C,i=n;i>0;i--){
    		if(V[i][j]>V[i-1][j]){
    			x[i]=1;
    			j=j-w[i];
    		}
    		else
    			x[i]=0;
    	}
    	return x;//输出所选物品 
    }
    
    int main(){
    	int w[]={0,2,2,6,5,4};
    	int v[]={0,6,3,5,4,6};
    	int C = 10;
    	int len = 5,i,value = 0;
    	
    	//求时间花费 
    	LARGE_INTEGER nFreq;
        LARGE_INTEGER nBeginTime;
        LARGE_INTEGER nEndTime;
        double time;
    	QueryPerformanceFrequency(&nFreq);
    	QueryPerformanceCounter(&nBeginTime);
    	//计时代码区间
    	 
    	int *result = KnapSack(w,v,len,C);
    	
    	QueryPerformanceCounter(&nEndTime);
    	time=(double)(nEndTime.QuadPart-nBeginTime.QuadPart)*1000000000/(double)(nFreq.QuadPart);
    	//不计时代码区间 
    	for(i=1;i<=len;i++){
    		if(result[i]==0)
    			continue;
    		else
    			cout<<i<<" ";//输出所选物品的序号 
    	}
    	cout<<endl;
    	for(i=1;i<=len;i++){
    		value += v[i]*result[i];
    	}
    	cout<<"取得的最大价值为:"<<value<<endl;
        cout  << time; //单位是纳秒.
    	
    	return 0;
    }