算法分析与设计(四、蛮力法求解0-1背包问题)

算法分析与设计(四、蛮力法求解0-1背包问题)

1、求完全数

        编写一个程序,输出2~10000之间的所有完全数。所谓完全数,是指这样的数,该数的各因子(除该数本身外)之和正好等于该数本身,例如:
  6=1+2+3
  28=1+2+4+7+14

#include <iostream>
using namespace std;

int main()
{	
	int m, s, j;
	for (m = 2; m <= 10000; m++) {
		s = 0;
		for (int j = 1; j <= m / 2; j++){
			if (m % j == 0)
				s += j;
		}
		if (m == s) 
			cout << s << "  ";
	}
}

2、求解幂集问题

        问题描述:对于给定的正整数n(n≥1),求1~n构成的集合的所有子集(幂集)。
        幂集(Power Set):原集合中所有的子集(包括全集和空集)构成的集族
        例如:n为3时,集合为:{1, 2, 3}
        所有的子集为:{}, {1}, {2}, {3}, {1,2}, {1,3}, {2,3}, {1,2,3}

1、两个数组,一个数据初始化为1到n,另一个数组初始化为1到n
2、set方法,输出2n个子集,也就是说共进行2n次循环,每次循环里再遍历数组,如果b[i]等于1,则a[i]输出(存在于要输出的子集),
3、2n次循环中最后要让b数组进行一次改变,相当于2进制数+1

#include <iostream>
using namespace std;

int num = 0;

void inc(int b[], int n) {
	num++;
	for (int i = 0; i < n; i++) {
		if (b[i]) {
			b[i] = 0;
		}
		else {
			b[i] = 1;
			break;
		}
	}
}
void set(int a[], int b[], int n) {//求幂集

	int i, k;
	int pw = (int)pow(2.0, n);
	cout << "1~" << n << "的幂集" << endl;
	for (i = 0; i < pw; i++) {	//枚举范围
		cout << "{ ";
		for (k = 0; k < n; k++) {
			if (b[k]) {		   //约束条件	
				cout << a[k] << " ";
			}
		}
		cout << "}";
		inc(b, n);	//二进制+1
	}

}
void main() {
	int n;
	cout << "输入幂集的正整数:" << endl;
	cin >> n;
	int a[100], b[100];
	for (int i = 0; i < n; i++) {;
		a[i] = i + 1;	    //a的初始化为{1,2,3}
		b[i] = 0;		//b的初始化为{0,0,0}
	}
	set(a, b, n);
}


3、0-1背包问题

        有n个重量分别为{w1,w2,…,wn}的物品,它们的价值分别为{v1,v2,…,vn},给定一个容量为W的背包。
        设计从这些物品中选取一部分物品放入该背包的方案,每个物品要么选中要么不选中,要求选中的物品不仅能够放到背包中,使得装入背包中物品的总价值最大。

#include <iostream>
using namespace std;


void inc(int b[], int n) {
	for (int i = 0; i < n; i++) {
		if (b[i]) {
			b[i] = 0;
		}
		else {
			b[i] = 1;
			break;
		}
	}
}
void set(int a[], int b[], int n, int w[], int v[], int W) {
	int maxi, maxsumw = 0, maxsumv = 0;
	int pw = (int)pow(2.0, n);
	cout << "0/1背包求解方案" << endl;
	cout << "  序号\t" << "选中物品\t" << "总重量\t" << "总价值\t" << "能否装入\t" << endl;
	for (int i = 0; i < pw; i++) {
		cout << "  " << i + 1 << "\t" << "{";
		int sumw = 0, sumv = 0;
		for (int j = 0; j < n; j++) {
			if (b[j]) {
				sumw += w[j];
				sumv += v[j];
				cout << a[j];

			}
		}

		cout << "}\t\t" << sumw << "\t" << sumv << "\t";
		if (sumw <= W) {
			cout << "能" << endl;
			if (sumv > maxsumv) {			//判断是否为当前最优方案
				maxi = i + 1;
				maxsumw = sumw;
				maxsumv = sumv;
			}
		}
		else {
			cout << "否" << endl;
		}
		inc(b, n);
	}
	cout << "最佳方案为:序号" << maxi << ",总重量:" << maxsumw << ",总价值:" << maxsumv;
}

void main() {
	int n = 4, W = 6;
	int w[] = { 5,3,2,1 }, v[] = { 4,4,3,1 };
	int a[100], b[100];
	for (int i = 0; i < n; i++)
	{
		a[i] = i + 1;		//初始化a  {1,2,3,4}
		b[i] = 0;			//初始化b  {0,0,0,0}
	}
	set(a, b, n, w, v, W);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值