1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h> // 包含的头文件不解释
typedef bool int // 因为标准c里边没有bool类型才这么做
#define false 0
#define true 1
int *c, // 将整个行列式的值存到c指向的空间里
n = 0, // 记录当前的行列式计算进行了多少步
a, // 方便传递行列式的阶数
sum = 0; // 记录每一步行列式计算所累加的结果
// 计算阶乘的函数
int aq(int a) {
int s = 1;
for (int i = 1; i <= a; i++)
s *= i;
return s;
}
void swap(int *a, int *b) {
int m = *a;
*a = *b;
*b = m;
}
// 计算在行列式计算过程中每一项前边的符号是正还是负
bool sa(int *l) {
int n = 0; // n为行列式展开式每一项的逆序数
for (int i = 0; i < a - 1; i++)
for (int j = i + 1; j < a; j++)
if (l[i] > l[j])
n++; // 不断通过条件判断累加逆序数得出最终的逆序数
if (n % 2 == 0)
return false; // 若为正,则返回false
return true; // 否则返回true
}
// 整个程序里边的核心函数,找出在不同行不同列的所有组合
void perm(int *l, int k, int m) {
int i, s = 1;
if (k > m) {
n++; // 每递归回来一次,将记录运行次数加一
for (int j = 0; j < a; j++)
s *= c[l[j] + a * j]; // 算出此次行列式展开式的这项的值
if (sa(l))
s * = -1; // 确定这一项的符号
// 输出当前sum内的值(即到当前为止所得到的结果是多少)
// 输出运行的完成程度(即当前运行的次数除以总次数)
printf("%5d 完成度:%2.2f%%\n", sum + = s, n / (aq(a) * 0.1) * 10);
} else {
for (i = k; i <= m; i++) {
swap(l + k, l + i);
perm(l, k + 1, m);
swap(l + k, l + i);
}
}
}
void main()
{
int *
b, // 一个辅助变量,在递归函数中将b指向的空间内的值进行全排列,也即行列式展开式不同组合的下标
i, // 循环中的辅助变量
f, // 在格式化输出行列式的辅助变量
e; // 判断是否退出程序的标志位
system("color 3e"); // 设置程序运行的前景色和背景色
u:
system("cls"); // 清空屏幕
printf("请输入行列式的阶数:\n");
scanf("%d", &a); // 获取行列式的阶数
b = (int *)malloc(sizeof(int) * a); // 为变量申请空间
c = (int *)malloc(sizeof(int) * a * a);
for (i = 0; i < a; i++)
*(b + i) = i; // 为辅助变量也即行列式下标逐个赋值
for (i = 0; i < a * a; i++) {
if (i % a == 0)
printf("请依次输入行列式中第%d行的值(以空格分隔):\n",
i / a + 1); // 提示输入行列式的值
scanf("%d", c + i);
}
printf("\n\n");
perm(b, 0, a - 1); // 计算行列式的值
printf("\n行列式展开式共有%d项\n", aq(a)); // 打印出来行列式的各种信息
if (a % 2 != 0)
f = a + 1; // 判断当前的行列式是偶数行还是奇数行
else
f = a;
for (i = 0; i < a * a; i++) {
if (i / a + 1 == f / 2 && i % a == 0) // 判断是否达到行列式中间的一行行首
printf("D = "); // 输出“D = ”
else if (i % a ==
0) // 判断是否是每一行的行首,若是则输出四个空格,保证输出的格式优美
printf(" ");
if (i % a == 0) // 判断是否是行首,若是输出制表符竖线,可与上一句写到一块儿
printf("┃");
if ((i + 1) % a == 0) // 判断是否是行列式某一行的最后一个数
printf("%2d", *(c + i));
else
printf("%2d ",
*(c + i)); // 若不是行列式某一行的最后一个数则在数字后边加一个空格
if ((i + 1) % a == 0) // 判断是否到达一行的行末
printf("┃");
if ((i + 1) / a == f / 2 &&
(i + 1) % a == 0) // 判断是否达到行列式中间一行的行末,输出整个行列式的值
printf(" = %d\n", sum);
else if ((i + 1) % a == 0) // 判断是否到达行末输出换行
printf("\n");
}
printf("\n\n");
printf("是否继续?( 1 / 0 )\n"); // 提示是否退出
scanf("%d", &e);
n = 0; // 每次都将都将上一次的运行记录消除
if (e == 1)
goto u; // 判断是否推出
else if (e == 0)
exit(0);
}
|