算法导论 · 回溯算法 · 子集和数问题

  • 算法说明
    求解201内,任意多个质数和为201的解的个数,构造向量解的过程
  • 源代码
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;

#define maxn 10000
#define M 201
int prime[maxn], isPri[maxn], num = 0; //prime中都是小于等于M的质数 
int x[maxn]; //解向量 
int ans = 0;

bool isPrime(int n) {
	int sqr = sqrt(n * 1.0);
	for(int i = 2; i <= sqr; i++) {
		if(n % i == 0) {
			return false;
		}
	}
	return true;
}

void findPrimeOL(int n) {
	for(int i = 2; i <= n; i++) {
		if(isPri[i]) {
			prime[num++] = i;
		}
		for(int j = 0; j < num; j++) {
			if(prime[j] * i > n) break;
			isPri[prime[j] * i] = false;
			if(i % prime[j] == 0) break;
		}
	}
}

void subset(int sum, int remaining, int k) {
	x[k] = 1;
	if(sum + prime[k] == M) {
		ans++;
//		for(int i = 0; i < num; i++) {
//			if(x[i] == 1) {
//				printf("%d ", prime[i]);
//			}
//		}
//		printf("\n");
	}
	else if(sum + remaining >= M && sum + prime[k] + prime[k + 1] <= M) {
		subset(sum + prime[k], remaining - prime[k], k + 1);
	}
	x[k] = 0;
	if(sum + remaining - prime[k] >= M && sum + prime[k + 1] <= M) {
		subset(sum, remaining - prime[k], k + 1);
	}
}
int main() {
	memset(prime, 0, sizeof(prime));
	memset(isPri, -1, sizeof(isPri));
	memset(x, 0, sizeof(x));
	findPrimeOL(M);
//	for(int i = 0; i < num; i++) {
//		printf("%d  ", prime[i]);
//	}
	
	int remaining = 0;
	for(int i = 0; i < num; i++) {
		remaining += prime[i];
	}
	
//	printf("%d  %d\n", remaining, num);
	subset(0, remaining, 0);
	
	printf("ans = %d", ans);
	return 0;
} 
  • 运行结果
    在这里插入图片描述
发布了77 篇原创文章 · 获赞 40 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/y_dd6011/article/details/97566574