例31   全排列问题

题目描述

输出自然数1到n所有不重复的排列,即n的全排列,要求所产生的任一数字序列中不允许出现重复的数字。

输入格式

n(1≤n≤9)

输出格式

由1~n组成的所有不重复的数字序列,每行一个序列。序列中每个数字占5个宽度。

输入样例

3

输出样例

1    2    3

1    3    2

2    1    3

2    3    1

3    1    2

3    2    1

(1)编程思路。

采用递归的方法来生成全排列。

(2)源程序。

#include <stdio.h>

int a[9],flag[10]={0};

void dfs(int pos,int n)

{

if (pos==n)  // 已有n个数

{

for (int i=0;i<n;i++)

printf("%5d",a[i]);

printf("\n");

}

else

{

for(int i=1;i<=n;i++)

{

if(flag[i])

continue;

a[pos]=i;

flag[i]=1;

dfs(pos+1,n);

flag[i]=0;

}

}

}

int main()

{

int n;

scanf("%d",&n);

dfs(0,n);

return 0;

}

习题31

31-1  选书

本题选自洛谷题库 (https://www.luogu.org/problem/P1657)

题目描述

学校放寒假时,信息学奥赛辅导老师有1,2,3……x本书,要分给参加培训的x个人,每人只能选一本书,但是每人有两本喜欢的书。老师事先让每个人将自己喜欢的书填写在一张表上。然后根据他们填写的表来分配书本,希望设计一个程序帮助老师求出所有可能的分配方案,使每个学生都满意。

输入格式

第1行:一个数x

第2行~第1+x行:每行两个数,表示ai喜欢的书的序号

输出格式

只有一个数:总方案数total。

输入样例

5

1 3

4 5

2 5

1 4

3 5

输出样例

2

(1)编程思路。

编写递归函数void dfs(int i,int n)表示第i个人在n本书中选择一本书。若第j本书(1≤j≤n)没选(标记数组元素f[j]=1)且第i个人喜欢这本书(数组元素a[i][j]的值也为1),则

第i个人选择第j本书;之后第i+1个人进行选择,递归调用dfs(i+1,n)。若n个人均选择好,则计数。

(2)源程序。

#include <stdio.h>

int a[21][21],f[21],cnt;  // a[i][j]第i个人喜欢第j本书

void dfs(int i,int n)

{

int j;

for(j=1;j<=n;j++)

{

if(f[j] && a[i][j]) // 这本书没选且第i个人喜欢这本书

{

f[j]=0;

if(i==n)

{

cnt++;

}

else

{

dfs(i+1,n);

}

f[j]=1;

}

}

}

int main()

{

int n,i,x,y;

scanf("%d",&n);

for(i=1;i<=n;i++)

{

scanf("%d%d",&x,&y);

a[i][x]=1;

a[i][y]=1;

f[i]=1;

}

dfs(1,n);

printf("%d\n",cnt);

return 0;

}

31-2  差三角形

问题描述

观察下面的数字组成的三角形:

3

1 4

5 6 2

看出什么特征吗?

1)它包含了1~6的连续整数。

2)每个数字都是其下方相邻的两个数字的差(当然是大数减去小数)

满足这样特征的三角形,称为差三角形。

编写程序,找出由1~n*(n+1)/2共n*(n+1)/2个整数组成的一个差三角形。

输入格式

一个正整数n。n≤6

输出格式

输出所有满足要求的差三角形。输出时,每个数字占4列。每种解之间空一行。

当无解的时候,请什么也不输出。

输入样例

4

输出样例

4

3

4   7

5   9   2

6   1  10   8

3

5   2

4   9   7

6  10   1   8

4

2   6

5   7   1

8   3  10   9

4

5   1

2   7   6

8  10   3   9

(1)编程思路。

先确定最后一行的值,即在1~ n*(n+1)/2这n*(n+1)/2个数中任意选取n个元素进行全排列。之后,按差三角形的特征依次确定上面其它行的值。在确定值的过程中,若某个值已被使用,则不可能是问题的解。直接剪枝,进行下次搜索。

(2)源程序。

#include <stdio.h>

void judge(int take[],int n)

{

int visited[22];  // 最多6行,21个数

int num[6][6],i,j,x;

for (i=1;i<=n*(n+1)/2;i++)

visited[i]=0;

for(i = 0; i < n; i++)

{

num[n-1][i]=take[i];

visited[take[i]] = 1;

}

for (i=n-2; i>=0; i--)

for (j = 0; j <= i; j++)

{

x = abs(num[i+1][j] - num[i+1][j+1]);

if(visited[x])

return;

if(x>=1 && x<= n*(n+1)/2)

{

visited[x] = 1;

num[i][j] = x;

}

}

if  (num[n-1][0]>num[n-1][n-1]) return ;

for (i = 0; i < n; i++)

{

for(j = 0; j<=i; j++)

printf("%4d",num[i][j]);

printf("\n");

}

printf("\n");

}

void dfs(int take[], int index,int vis[],int n)

{

int i, j;

if (index==n)

{

judge(take,n);

return;

}

for(i = 1; i <= n*(n+1)/2; i++)

{

if(!vis[i])

{

vis[i] = 1;

take[index]= i;

dfs(take, index+1,vis,n);

vis[i] = 0;

}

}

}

int main()

{

int n,take[6],i;

int vis[22];

scanf("%d",&n);

for(i = 1; i <= n*(n+1)/2; i++)

vis[i]=0;

dfs(take,0,vis,n);

return 0;

}

31-3 数字和

问题描述

写出一个1至n的排列a1,a2,…,an,然后每次将相邻两个数相加,构成新的序列,再对新序列进行这样的操作,显然每次构成的序列都比上一次的序列长度少1,直到只剩下一个数字位置。下面是一个例子:

3 ,1,2,4

4,3,6

7,9

16

最后得到16这样一个数字。

如果知道n和最后得到的数字的大小sum,请你求出最初序列a1,a2,…,an,这个序列为1至n的一个排列。若答案有多种可能,则输出字典序最小的那一个。

注意:本题字典序指的是1,2,3,4,5,6,7,8,9,10,11,12,而不是1,10,11,12,2,3,4,5,6,7,8,9。

输入格式

两个正整数n,sum。n≤12,sum≤12345。

输出格式

输出包括1行,为字典序最小的那个答案。

当无解的时候,请什么也不输出。

输入样例

4 16

输出样例

3 1 2 4

(1)编程思路。

以题目示例来说明。4个数a1、a2、a3、a4

第1次得到: a1+a2、a2+a3、a3+a4

第2次得到:a1+a2+a2+a3、a2+a3+a3+a4

第3次得到:(a1+a2+a2+a3)+(a2+a3+a3+a4)

即最后总和为:a1+3*a2+3*a3+a4

系数1、3、3、1正好四杨辉三角形的第4行的值。因此,需要先求出杨辉三角形第n行的值,以便于最后总和的计算。

生成1~n的全排列,对生成的排列进行判断,看是否满足和值等于输入的sum,如果找到的答案,置标记found为1,之后各排列直接返回。

(2)源程序。

#include <stdio.h>

int a[12],flag[13]={0},y[13]={0};

int n,sum,found=0;

void dfs(int pos,int cursum)

{

if (cursum>sum|| found==1) return;

if (pos==n)

{

if (cursum==sum)

{

for (int i=0;i<n;i++)

printf("%d ",a[i]);

printf("\n");

found=1;

}

}

else

{

for(int i=1;i<=n;i++)

{

if(flag[i])

continue;

a[pos]=i;

flag[i]=1;

dfs(pos+1,cursum+a[pos]*y[pos]);

flag[i]=0;

}

}

}

int main()

{

scanf("%d%d",&n,&sum);

y[0]=1;

for (int row=1;row<n;row++)

for (int col=row;col>=1;col--)

y[col]=y[col]+y[col -1];

dfs(0,0);

return 0;

}

C语言程序设计100例之(31):全排列问题的更多相关文章

  1. 黑马程序员——经典C语言程序设计100例

    1.数字排列 2.奖金分配问题 3.已知条件求解整数 4.输入日期判断第几天 5.输入整数进行排序 6.用*号显示字母C的图案 7.显示特殊图案 8.打印九九口诀 9.输出国际象棋棋盘 10.打印楼梯 ...

  2. C语言程序设计100例之(6):数字反转

    例6    数字反转 题目描述 给定一个整数,请将该数各个位上数字反转得到一个新数.新数也应满足整数的常见形式,即除非给定的原数为零,否则反转后得到的新数的最高位数字不应为零(参见样例2). 输入格式 ...

  3. C语言程序设计100例之(25):确定进制

    例25    确定进制 问题描述 6*9 = 42 对于十进制来说是错误的,但是对于13进制来说是正确的.即 6(13)* 9(13)= 42(13),因为,在十三进制中,42 = 4 * 13 + ...

  4. C语言程序设计100例之(22):插入排序

    例22  插入排序 问题描述 排序是计算机程序设计中的一种重要操作,它的功能是将一个数据元素或记录的任意序列,重新排列成一个以关键字递增(或递减)排列的有序序列. 排序的方法有很多,简单插入排序就是一 ...

  5. C语言程序设计100例之(16):巧解算式

    例16  巧解算式 问题描述 在1.2.3.4.5.6.7.8.9.10个数中间加上加号或减号,使得到的表达式的值为自然数N,如果中间没有符号,则认为前后为一个数,如1 2 3认为是一百二十三(123 ...

  6. C语言程序设计100例之(15):除法算式

    例15   除法算式 问题描述 输入正整数n(2≤n≤68),按从小到大输出所有形如abcde/fghi=n的表达式.其中a~i为1~9的一个排列. 输入格式 每行为一个正整数n (n <= 1 ...

  7. C语言程序设计100例之(9):生理周期

    例9    生理周期 问题描述 人生来就有三个生理周期,分别为体力.感情和智力周期,它们的周期长度为 23 天.28 天和33 天.每一个周期中有一天是高峰.在高峰这天,人会在相应的方面表现出色.例如 ...

  8. C语言程序设计100例之(3): Cantor表

    例3    Cantor表 题目描述 现代数学的著名证明之一是Georg Cantor证明了有理数是可枚举的.他是用下面这一张表来证明这一命题的: 1/1  1/2  1/3  1/4  …… 2/1 ...

  9. C语言程序设计100例之(26):二进制数中1的个数

    例26   二进制数中1的个数 问题描述 如果一个正整数m表示成二进制,它的位数为n(不包含前导0),称它为一个n位二进制数.所有的n位二进制数中,1的总个数是多少呢? 例如,3位二进制数总共有4个, ...

随机推荐

  1. Codeforces 558E A Simple Task(计数排序+线段树优化)

    http://codeforces.com/problemset/problem/558/E Examples input 1 abacdabcda output 1 cbcaaaabdd input ...

  2. html5 一些好用的原生事件

    计算机技术发展这么多年, 有些方面太老了,不适合新时代的发展, 使用新的规范,更方便开发和使用, 提高各方使用人的工作效率, 何乐而不为 drag drop html5新增属性 某些操作使用拖拽比较方 ...

  3. Linux_拷贝,剪切,删除和创建文件

    cp 你要拷贝的文件 + 目录/带路径的文件名(在拷贝的同时,让这个文件重新命名) cp /tep/dir01  ~  代表将dir01拷贝到当前用户的家目录中 cp /tep/dir02  ~/di ...

  4. Web Service概述 及 应用案例

    Web Service的定义  W3C组织对其的定义如下,它是一个软件系统,为了支持跨网络的机器间相互操作交互而设计.Web Service服务通常被定义为一组模块化的API,它们可以通过网络进行调用 ...

  5. QLIKVIEW基础设置及初步了解

    改变语言环境 开发工具条勾选出来 创建selection box 创建search box 编辑脚本 重加载数据 基本联动思路:table view tableview load FSUPPLIERI ...

  6. Django连接SQL Server,安装相关扩展包及相关配置

    1.python下载 https://www.python.org/downloads/windows/ 2.根据当前windows和python的版本,下载pymssql相应的exe安装文件. ht ...

  7. perf4j+logback配置 非spring 可使用注解

    最近项目打算使用perf4j进行性能监控,由于项目没有使用spring,而又不想对代码入侵过高,打算使用注解的方式进行接入.perf4j采用AspectJ库实现AOP. 具体接入方法如下: logba ...

  8. vue项目中net::ERR_CONNECTION_TIMED_OUT错误

    我出错的原因时network地址与我本机ip地址不一致 Network: http://192.168.13.30:8080/ 处理方法: 在vue项目中新建一个vue.config.js文件 配置上 ...

  9. 从NIPS2014大会看机器学习新趋势

    微软杰出科学家 John Platt 本文译自:Machine Learning Trends fromNIPS 2014 编者按:John Platt是微软的杰出科学家,也是微软在机器学习领域的领军 ...

  10. [SDOI2006] 线性方程组

    洛谷 P2455 传送门 刚开始写了个消成上三角的,结果狂wa. 后来经过研究发现,消成上三角那种不能直接判断无解或无穷多解,需要其它的操作. 所以干脆学了个消成对角线的,写了一发A了. 其实两种消元 ...