动态循环:多个数组之间的组合问题+2018北京理工上机哥德巴赫猜想

  1. 题目:
    多个数组(个数未知可变),每个数组中的个数不一定相同,从每个数组中挑一个,得到一个组合。输出所有的组合形式
  2. 方法
    采用递归,如下
    void 做多次循环(循环次数){
    次数小于一,直接退出;
    次数等于一,(即到达出口,只剩最后一个数组)每次先将之前路径内容输出,在输出最后一个数组的一个元素。
    否则,将当前数组遍历,加入到路径中,并做多次循环(循环次数-1);
    最后,将这次压入的数据弹出(已经用过了)
    }
  3. 要点
    一因为需要正向输出路径的元素,使用vector的push_back()和pop_back(),遍历则直接
    for(auto i: vec) { cout<<i<<’ ';}
    一注意执行完判断之后的pop是关键,将末尾已经输出的元素换成下一个同数组的元素
    一循环次数和level的方向一致,可以作为下标使用,递减时默认第一个数组是最后一组
  4. 代码
#include <iostream>
#include<algorithm>
#include<vector>
#include<fstream>
using namespace std;

const vector<char> num[4] = { {},{'A','a'},{'b','B'},{'C'} };
vector<char> prePath;
void doLoops(int level) {
	if (level <= 0) return;
	if (level == 1) {
		for (int i = 0; i < num[level].size(); i++) {
			for (auto i : prePath) { cout << i << " "; }
			cout << num[level][i] << endl;
		}
	}
	else {
		for (int i = 0; i < num[level].size(); i++) {
			prePath.push_back(num[level][i]);
			doLoops(level - 1);
		}
	}
	prePath.pop_back();
}

int main()
{
	doLoops(3);
	//循环次数和level的方向一致,可以作为下标使用,递减时默认第一个数组是最后一组
	system("pause");
	return 0;
}
  1. 应用题:
    任何一个大于2的偶数均可表示为两个素数之和。
    输入m, n(6<=m<=n<=50),则把[m, n]内的所有偶数表示成两个素数之和的形式。
    输出这些《素数,出现次数》;输出次序按次数从多到少输出;若次数相同,按照素数从大到小输出;若偶数有多种素数相加形式,则把所有的情况都输出,每种情况占一行。
输入:8 10  输出:
5 3 3 1
3 2 7 1 5 1

方法:
先拆成多个《素数,次数》数组的数组,组合其结果,对结果排序后输出
例如,8得到一个数组{《3,一次》《5,一次》},记为arr1
10得到{《3,一次》,《7,一次》}和{《5,两次》}两个数组arr2,arr3
即化为{arr1}与{arr2,arr3}的组合问题

细节:

  • 定义数组为vector<vector < PrimeNode > > m_table[M];
    M为具体偶数的个数(相当于level指向对应的偶数),在不同level(即不同的偶数下)可以有多个拆分组合(vector < PrimeNode >),可以通过m_table[level][分解方案]锁定方案数组

  • 素数拆分,数据不多,直接打表即可,isPrime[当前数]&&isPrime[偶数-当前数],当两个数刚刚好一样,次数为二,当前数据不会大于偶数的一半

  • 结构体排序,注意两点一排序的是下标cmp函数中传入的是order【i】和order【j】,而cmp函数的写法,先后关系用if(第一条件不等时)···else if(第二条件)···

  • 用map计数之后赋值给vector进行排序
    vector<pair<int, int>> sortTable(counTable.begin(),counTable.end());

  • for外定义的数据,相对于for是全局变量,在循环中每次都要清空如

vector<PTnode> temp;
for (int i = 2; i <= num/2; i++) {//细节
			temp.clear();//细节
  • 操作执行前需要有效,简单的下标一定合法,而pop之前需要保证容器不空

代码

#include <iostream>
#include<cmath>
#include<vector>
#include<map>
#include<fstream>
using namespace std;
#define see(x) cout<<x<<endl

typedef struct PrimeTimesNode {
	int prime;
	int times;
	PrimeTimesNode(int p,int t):prime(p),times(t) {
	}
	void showNode() {
		printf_s("[%d,%d] ", prime, times);
	}
}PTnode;

bool g_isPrime[51] = { false };

class Sol
{
public:
	Sol() {}
	Sol(int m,int n):m_level(0){
		getTable(m,n);
		doLoops(m_level);
	}
	~Sol() {}


	void readInfo() {
		//"C:\\Users\\dell\\source\\repos\\find_ci_xu\\Main\\test.txt"
		fstream fin("test.txt", ios::in);

		fin.close();
	}
	void getTable(int m,int n) {
		//int level = 0;
		for (int i = m; i <= n; i++) {
			if (i % 2 == 0) {
				++m_level;
				getSplitPrimes(i);
			}
		}
	}
	void getSplitPrimes(int num) {
		vector<PTnode> temp;
		for (int i = 2; i <= num/2; i++) {//细节
			temp.clear();//细节
			if (!g_isPrime[i] && !g_isPrime[num - i]) {
				if (i + i == num) {
					temp.push_back(PTnode(i, 2));
				}
				else {
					temp.push_back(PTnode(i, 1));
					temp.push_back(PTnode(num - i, 1));
				}
				m_table[m_level].push_back(temp);
			}
		}
	}
	

	void doLoops(int level)
	{
		if (level <= 0)
			return;
		if (level == 1)
		{
			int s = m_table[level].size();
			for (int i = 0; i <s ; i++)
			{
				m_prePath.push_back(m_table[level][i]);
				
				readPath();

				m_prePath.pop_back();
			}
		}
		else
		{
			int s = m_table[level].size();
			for (int i = 0; i < s; i++)
			{
				m_prePath.push_back(m_table[level][i]);
				doLoops(level - 1);
			}
		}
		if(!m_prePath.empty())//将一个无效参数传递给了将无效参数视为严重错误的函数
		m_prePath.pop_back();
	}

	void readPath() {
		map<int, int> counTable; counTable.clear();
		for (auto i : m_prePath) {
			for (auto j : i) {
				//j.showNode();//test
				if (counTable.find(j.prime) == counTable.end()) {
					counTable.insert(make_pair(j.prime, j.times));
				}
				else {
					counTable[j.prime] += j.times;
				}
			}
		}
		
		vector<pair<int, int>> sortTable(counTable.begin(),counTable.end());
		sortandPrint(sortTable);
		
	}
	void sortandPrint(vector<pair<int, int> > &sortTable) {
		int size = sortTable.size();

		vector<int> order;
		for (int i = 0; i < size; i++) {
			order.push_back(i);
		}

		for (int i = 0; i < size; i++) {
			bool hasChange = false;
			for (int j = 0; j + 1 < size; j++) {
				if (cmp(order.at(j), order[j + 1], sortTable)) {//细节
					swap(order.at(j), order[j + 1]);
					hasChange = true;
				}
			}
			if (!hasChange) break;
		}

		for (int i = 0; i < size; i++) {
			int ptr = order[i];
			printf_s("[%d %d] ", sortTable[ptr].first, sortTable[ptr].second);
		}
		printf_s("\n");
		sortTable.clear();
	}
	bool cmp(int i, int j, vector<pair<int, int> > &sortTable) {
		if (sortTable[i].second != sortTable[j].second) {
			return sortTable[i].second < sortTable[j].second;
		}else{
			return sortTable[i].first < sortTable[j].first;
		}
	}
	
	
private:
	vector<vector<PTnode> > m_table[25];
	vector<vector<PTnode> > m_prePath;
	int m_level;
};

void getIsPrime() {
	g_isPrime[0] = g_isPrime[1] = true;//true means not prime

	for (int i = 2; i <= 50; i++) {
		if (!g_isPrime[i]) {
			for (int j = i + i; j <= 50; j += i) {
				g_isPrime[j] = true;
			}
		}
	}
}
int main()
{
	getIsPrime();
	Sol test(8,15);
	
	system("pause");
	return 0;
}


  • 优化函数和逻辑关系
#include <iostream>
#include<cmath>
#include<vector>
#include<map>
#include<fstream>
using namespace std;
#define see(x) cout<<x<<endl

//names

typedef pair<int, int> PTimes;//prime times
typedef vector<PTimes> Solution;//分解方案
typedef vector<int> PTorder;//排序结果

//global var
bool g_isPrime[51] = { false };

class Sol
{
public:
	Sol() {}
	Sol(int m,int n):m_level(0){
		getTable(m,n);
		doLoops(m_level);
	}
	~Sol() {}


	void readInfo() {
		//"C:\\Users\\dell\\source\\repos\\find_ci_xu\\Main\\test.txt"
		fstream fin("test.txt", ios::in);

		fin.close();
	}
	void getTable(int m,int n) {
		for (int i = m; i <= n; i++) {
			if (i % 2 == 0) {
				++m_level;
				getSplitPrimes(i);
			}
		}
	}
	void getSplitPrimes(int num) {
		for (int i = 2; i <= num/2; i++) {//细节
			Solution temp;
			if (!g_isPrime[i] && !g_isPrime[num - i]) {
				if (i + i == num) {
					temp.push_back(make_pair(i, 2));
				}
				else {
					temp.push_back(make_pair(i, 1));
					temp.push_back(make_pair(num - i, 1));
				}
				m_table[m_level].push_back(temp);
			}
		}
	}
	

	void doLoops(int level)
	{
		if (level <= 0)
			return;
		if (level == 1)
		{
			int s = m_table[level].size();
			for (int i = 0; i <s ; i++)
			{
				m_prePath.push_back(m_table[level][i]);

				showAns();
			
				m_prePath.pop_back();
			}
		}
		else
		{
			int s = m_table[level].size();
			for (int i = 0; i < s; i++)
			{
				m_prePath.push_back(m_table[level][i]);
				doLoops(level - 1);
			}
		}
		if(!m_prePath.empty())//将一个无效参数传递给了将无效参数视为严重错误的函数
		m_prePath.pop_back();
	}

	void showAns() {
		PTorder order;
		Solution countAns;

		readPath(countAns);
		sort(countAns,order);
		print(countAns,order);
	}


	void readPath(Solution &countAns) {
		map<int, int> counTable; 
		for (auto sol : m_prePath) {
			for (auto pt : sol) {
				if (counTable.find(pt.first) == counTable.end()) {
					counTable.insert(pt);
				}
				else {
					counTable[pt.first] += pt.second;
				}
			}
		}
		
		for (auto it = counTable.begin(); it != counTable.end(); it++) {
			//cout << (*it).first <<" "<< (*it).second << "||";
			countAns.push_back(*it);
		}
		
	}


	void sort(Solution &countAns,PTorder &order) {
		int size = countAns.size();
		
		for (int i = 0; i < size; i++) {
			order.push_back(i);
		}

		for (int i = 0; i < size; i++) {
			bool hasChange = false;
			for (int j = 0; j + 1 < size; j++) {
				if (cmp(order.at(j), order[j + 1], countAns)) {//细节
					swap(order.at(j), order[j + 1]);
					hasChange = true;
				}
			}
			if (!hasChange) break;
		}
	
	}

	bool cmp(int i, int j, Solution &countAns) {
		if (countAns[i].second != countAns[j].second) {
			return countAns[i].second < countAns[j].second;
		}else{
			return countAns[i].first < countAns[j].first;
		}
	}

	void print(Solution& ans,PTorder& order) {
		for (int ptr:order) {
			printf_s("[%d %d] ", ans[ptr].first, ans[ptr].second);
		}
		printf_s("\n");
	}
	
private:
	vector<Solution > m_table[25];
	vector<Solution > m_prePath;
	int m_level;
};

void getIsPrime() {
	g_isPrime[0] = g_isPrime[1] = true;//true means not prime

	for (int i = 2; i <= 50; i++) {
		if (!g_isPrime[i]) {
			for (int j = i + i; j <= 50; j += i) {
				g_isPrime[j] = true;
			}
		}
	}
}
int main()
{
	getIsPrime();
	Sol test(8,10);
	
	system("pause");
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值