【求助】组合与排列的生成:先考虑组合生成程序,输入正整数m和n,1<=n<=m<1000, 输出从m个数中取出n个的所有组合

念言 2013-04-21 01:35:25
组合与排列的生成:先考虑组合生成程序,输入正整数m和n,1<=n<=m<1000, 输出从m个数中取出n个的所有组合。例如输入5,3,则应输出可以构成的所有组合123,124,125,234,235,345.....然后请再考虑排列生成程序,输入正整数m,1<m<1000, 输出m个数的全排列。例如输入3,输出应为123,231,312,132,321,213。本题要求给出较好的程序,即不应该是简单地用多重循环枚举所有可能的程序。(可查阅:吕国英,任瑞征等编著,算法设计与分析(第2版),清华大学出版社,2009年1月,65-68页,223-225页。)
求一个算法,,,很急,,,明早就要搞定。。。。
...全文
496 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
HUANGFEIDIAN 2013-04-23
  • 打赏
  • 举报
回复
引用 17 楼 u010391102 的回复:
其实我到现在还不懂,输入5 3 是怎样跑出123,124,125,234,235,345,,原理还不知道哎。。
首先是五个选3个组合,存入一个数组中,然后生成123的排列,根据排列出来的结果当作下标来输出数组。 事实上可以把排列结果直接也开另外一个二维数组来存,省得每一个组合输出的时候都得重新计算一次。 对于较小的数据,你就直接递归就行了。 对于大数据,我贴的那几个代码都是线性时间生成的,改一下那些宏定义就行了。 如果想知道原理,可以参考taocp第四卷。 其实高老爷子写的taocp让我看得巨不爽,还是直接去看论文吧。
regainworld 2013-04-23
  • 打赏
  • 举报
回复
1、c(5,3)组合得到所有数组,如(1,2,3),(1,3,4)。。。 2、p(3)全排列,结果如(1,2,3)、(1,3,2)。。。 3、全排列作为下标,输出1得到的数组就行了,如对(1,3,4),有(1,3,4)、(1,4,3)。。。
念言 2013-04-23
  • 打赏
  • 举报
回复
其实我到现在还不懂,输入5 3 是怎样跑出123,124,125,234,235,345,,原理还不知道哎。。
N3verL4nd 2013-04-22
  • 打赏
  • 举报
回复
#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
#include<set>
#include<string>
#include<queue>
#include <stack>
using namespace std;
#pragma warning(disable : 4996)
const int MAXN = 25;
int n, m;
int ans[MAXN];
int num[MAXN];
bool vis[MAXN];

void dfs(int x, int cnt)
{
	if(cnt == n + 1)
	{
		for(int i = 1; i <= n; i++)
		{
			cout << ans[i] << " ";
		}
		cout << endl;
		return;
	}
	for(int i = x; i <= m; i++)
	{
		if(!vis[i])
		{
			vis[i] = true;
			ans[cnt] = num[i];
			dfs(i, cnt + 1);
			vis[i] = false;
		}
	}
}


int main()
{
	while (cin >> m >> n)
	{
		for(int i = 1; i <= m; i++)
		{
			cin >> num[i];
		}
		memset(vis, false, sizeof(vis));
		dfs(1, 1);
	}
	return 0;
}
http://blog.csdn.net/lgh1992314/article/details/8831834
念言 2013-04-22
  • 打赏
  • 举报
回复
引用 10 楼 zhao4zhong1 的回复:
C/C++ code?1234567891011121314151617181920212223242526272829303132333435363738#include <stdio.h>#include <stdlib.h>#define MAX_NUM 26int comb[MAX_NUM];int c1,c2;void combination(int m,int……
难道是软件的问题?《VC++6.0啊》 为什么跑出来的结果 都是有问题的 而且还挺大的问题,,,
赵4老师 2013-04-22
  • 打赏
  • 举报
回复
#include <stdio.h>
#include <stdlib.h>
#define MAX_NUM 26
int comb[MAX_NUM];
int c1,c2;
void combination(int m,int n) {
    int i,j;

    for (i=m;i>=n;i--) {
        comb[n]=i; /* 选择当前的“头”元素 */
        if (n>1) {
            combination(i-1,n-1); /* 进入下一次更小的组合问题 */
        } else { /* 满了需要的组合数,输出 */
            for (j=comb[0];j>0;j--) printf("%c",'A'+c1-comb[j]);
            printf("\n");
        }
    }
    return;
}
int main(int argc,char **argv) {
    if (argc<3) {
        printf("%s 组合下标 组合上标\n",argv[0]);
        return 1;
    }
    c1=atoi(argv[1]);
    if (c1<1 || MAX_NUM<c1) {
        printf("1<=组合下标<=%d\n",MAX_NUM);
        return 2;
    }
    c2=atoi(argv[2]);
    if (c2<1 || c1<c2) {
        printf("1<=组合上标<=组合下标\n");
        return 3;
    }
    comb[0]=c2;
    combination(c1,c2);
    return 0;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int m;//记录字符串长度
int n;//记录字符串中的字符种类数
char map[256];//记录是哪几种字符
int count[256];//记录每种字符有多少个
int stack[1000];//递归用的栈,并记录当前生成的排列
void Make_Map(char *str) {//统计字符串的相关信息
    int s[256];
    int i;
    memset(s,0,sizeof(s));
    memset(count,0,sizeof(count));
    m=strlen(str);
    while(*str) {
        s[*str]++;
        str++;
    }
    n=0;
    for (i=0;i<256;i++)
        if (s[i]) {
            map[n]=i;
            count[n]=s[i];
            n++;
        }
}
void Find(int depth) {//递归式回溯法生成全排列
    if (depth==m) {
        int i;
        for (i=0;i<depth;i++) putchar(map[stack[i]]);
        putchar('\n');
    } else {
        int i;
        for (i=0;i<n;i++)
            if (count[i]) {
                stack[depth]=i;
                count[i]--;
                Find(depth+1);
                count[i]++;
            }
    }
}
void main(int argc,char**argv) {
    if (argc<2) {
        printf("%s 要产生全排列的字符串\n",argv[0]);
        return;
    }
    Make_Map(argv[1]);
    Find(0);
}
HUANGFEIDIAN 2013-04-22
  • 打赏
  • 举报
回复
引用 10 楼 zhao4zhong1 的回复:
C/C++ code?1234567891011121314151617181920212223242526272829303132333435363738#include <stdio.h>#include <stdlib.h>#define MAX_NUM 26int comb[MAX_NUM];int c1,c2;void combination(int m,int……
赵老师可否看一下我贴的那两个生成组合的代码。
念言 2013-04-22
  • 打赏
  • 举报
回复
其实全排列现在还能懂点 现在主要问题是在M个数中选取N个数并输出N个数的全排列 比如输入5 3 就是在1 2 3 4 5中选取3个数 有10种情况 然后假设选取的是1 2 3 然后输出 1 2 3的全排列 有6种情况 那总共就有60种情况了 那么输入5 3 输出的就是60个数组说的我都有点头大了 反正特麻烦 ,,,坑啊。。
HUANGFEIDIAN 2013-04-21
  • 打赏
  • 举报
回复
上面贴的那个组合算法是无分支算法,下面贴他的有分支形式

#include <stdio.h>
#include <malloc.h>
#define NUMBER_ONE 3
#define NUMBER_ZERO 2
#define NUMBER_TOTAL (NUMBER_ZERO+NUMBER_ONE)
int for_out[NUMBER_TOTAL];
void result_out()
{
	int for_i;
	for(for_i=0;for_i<NUMBER_TOTAL;for_i++)
	{
		printf("%d ",*(for_out+for_i));
	}
	printf("\n");
}
void swap(int from,int to)
{
	int temp;
	temp=*(for_out+from);
	*(for_out+from)=*(for_out+to);
	*(for_out+to)=temp;
}
void main()
{
	int for_i,for_j,for_x,for_y;
	for(for_i=0;for_i<NUMBER_ONE;for_i++)
	{
		*(for_out+for_i)=1;
	}
	for(for_i;for_i<NUMBER_TOTAL;for_i++)
	{
		*(for_out+for_i)=0;
	}
	result_out();
	for_x=for_y=NUMBER_ONE-1;
	while(for_x<NUMBER_TOTAL-1)
	{
		for_out[for_x]=0;
		for_out[for_y]=1;
		for_x++;
		for_y++;
		if(for_out[for_x]==0)
		{
			for_out[for_x]=1;
			for_out[0]=0;
			if(for_y>1)
			{
				for_x=1;
			}
			for_y=0;
		}
		result_out();
	}
}




HUANGFEIDIAN 2013-04-21
  • 打赏
  • 举报
回复
这个是n个位取m位的coolex方法

#include <stdio.h>
#include <malloc.h>
#define NUMBER_ONE 3
#define NUMBER_ZERO 2
#define NUMBER_TOTAL (NUMBER_ZERO+NUMBER_ONE)
int for_out[NUMBER_TOTAL];
void result_out()
{
	int for_i;
	for(for_i=0;for_i<NUMBER_TOTAL;for_i++)
	{
		printf("%d ",*(for_out+for_i));
	}
	printf("\n");
}
void main()
{
	int for_i,for_x,for_y;
	for(for_i=0;for_i<NUMBER_ONE;for_i++)
	{
		*(for_out+for_i)=1;
	}
	for(for_i;for_i<NUMBER_TOTAL;for_i++)
	{
		*(for_out+for_i)=0;
	}
	result_out();
	for_x=for_y=NUMBER_ONE-1;
	while(for_x<(NUMBER_TOTAL-1))
	{
		for_out[for_x]=0;
		for_out[for_y]=1;
		for_out[0]=for_out[for_x+1];
		for_out[for_x+1]=1;
		for_x=1+(for_x)*(1-(for_out[1])*(1-for_out[0]));
		for_y=for_out[0]*(for_y+1);
		result_out();
	}
}

HUANGFEIDIAN 2013-04-21
  • 打赏
  • 举报
回复
你要代码,给你就是 这个是n个数全排列的next_permutation方法
#include <stdio.h>
#include <malloc.h>
#define MAX 4
int  for_out[MAX];
int sum=0;
void out_put()
{
	int for_i;
	for(for_i=0;for_i<MAX;for_i++)
	{
		printf("%d ",for_out[for_i]);
	}
	printf("\n");
}
void reverse(int a)
{
	int for_i,temp,total;
	total=MAX-a;
	total=total/2;
	for(for_i=0;for_i<total;for_i++)
	{
		temp=for_out[a+for_i];
		for_out[a+for_i]=for_out[MAX-1-for_i];
		for_out[MAX-1-for_i]=temp;
	}
}


void main()
{
	int for_i,for_j,temp;
	for(for_i=0;for_i<MAX;for_i++)
	{
		for_out[for_i]=for_i;
	}
	for_i=1;
	while(1)
	{
		out_put();
		for_i=0;
		while((for_i<MAX-1)&&(for_out[MAX-1-for_i]<for_out[MAX-2-for_i]))
		{
			for_i++;
		}
		if(for_i==MAX-1)
		{
			return 1;
		}
		else
		{
			if(for_i==0)
			{
				temp=for_out[MAX-1];
				for_out[MAX-1]=for_out[MAX-2];
				for_out[MAX-2]=temp;
			}
			else
			{
				temp=for_out[MAX-2-for_i];
				for_j=MAX-1-for_i;
				while(for_j<MAX&&for_out[for_j]>temp)
				{
					for_j++;
				}
				for_out[MAX-2-for_i]=for_out[for_j-1];
				for_out[for_j-1]=temp;
				reverse(MAX-for_i-1);
			}
		}
	}
}




regainworld 2013-04-21
  • 打赏
  • 举报
回复
全排列4结果如下: 3 1 2 4 1 3 2 4 3 2 1 4 2 3 1 4 4 1 2 3 1 4 2 3 1 2 4 3 4 2 1 3 2 4 1 3 2 1 4 3 4 3 1 2 3 4 1 2 3 1 4 2 4 1 3 2 1 4 3 2 1 3 4 2 4 3 2 1 3 4 2 1 3 2 4 1 4 2 3 1 2 4 3 1 2 3 4 1 24 time is 0.072 seconds
regainworld 2013-04-21
  • 打赏
  • 举报
回复
求全排列啊,你把vector换成数组就是c语言 当然效率太低了,只是个思路而已
念言 2013-04-21
  • 打赏
  • 举报
回复
引用 3 楼 regainworld 的回复:
C/C++ code?12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758void GetArray(int n, vector<int> vTmp, vector<vector<int> > &vArr……
跟我那题木有半毛钱关系啊,,, 亲。。
regainworld 2013-04-21
  • 打赏
  • 举报
回复


void GetArray(int n, vector<int> vTmp, vector<vector<int> > &vArray)
{
	if (n == 1)
	{
		vTmp.push_back(n);
		vArray.push_back(vTmp);
		return;
	}

	GetArray(n-1, vTmp, vArray);

	unsigned int nArray = vArray.size();
	for (unsigned int i=0; i<nArray; i++)
	{
		for (int j=0; j<n-1; j++)
		{
			vTmp.assign(vArray[i].begin(), vArray[i].end());
			vTmp.insert(vTmp.begin()+j, n);
			vArray.push_back(vTmp);
		}
		vArray[i].push_back(n);
	}
}

void PrintArray(vector<vector<int> > &vArray)
{
	for (unsigned int i=0; i<vArray.size(); i++)
	{
		for (unsigned int j=0; j<vArray[i].size(); j++)
		{
			cout << vArray[i][j] << " ";
		}
		cout << endl;
	}
}

int main(int argc, char** argv)
{
	vector<vector<int> > vArray;
	vector<int> vTmp;

	GetArray(5, vTmp, vArray);
	//PrintArray(vArray);
	cout << vArray.size() << endl;
	vTmp.clear();
	vArray.clear();
	GetArray(10, vTmp, vArray);
	//PrintArray(vArray);
	cout << vArray.size() << endl;
    
    double t;    //计算运行时间的代码
    clock_t time;
    time=clock();
    t=(double)time/CLK_TCK;
    cout<<"time is "<<t<<"  seconds "<<endl;
	getchar();
    return 0;
}
regainworld 2013-04-21
  • 打赏
  • 举报
回复
组合,其中vTmp为临时数组,vSplit为输出数组,调用时均为空


#include <iostream>
#include <vector>
#include<time.h>

using namespace std;

void GetCompose(int n, int m, vector<int> vTmp, vector<vector<int> > &vSplit)
{
	if (n == m)
	{
		for (int i=m; i>=1; i--)
		{
			vTmp.push_back(i);
		}
		vSplit.push_back(vTmp);
		return;
	}

	// 不选n
	GetCompose(n-1, m, vTmp, vSplit);

	// 选n
	vTmp.push_back(n);
	if (m == 1)
	{
		vSplit.push_back(vTmp);
		return;
	}
	GetCompose(n-1,m-1, vTmp, vSplit);
};
念言 2013-04-21
  • 打赏
  • 举报
回复
跪求代码,,,

69,369

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧