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