#include<malloc.h>#include<stdio.h>#include<stdlib.h>//包含的頭文件不解釋#define bool int //因為標準c里邊沒有bool類型才這么做#define false 0#define true 1//定義幾個全局變量,無奈之舉int*c;//將整個行列式的值存到c指向的空間里int n =0;//記錄當前的行列式計算進行了多少步int a;//方便傳遞行列式的階數int sum =0;//記錄每一步行列式計算所累加的結果intaq(int a)//計算階乘的函數,就不多解釋了{int s =1;for(int i =1; i <= a; i ++)s *= i;return s;}voidswap(int*a,int*b)//利用地址傳遞,交換兩個數的值{int m =* a;* a =* b;*b = m;}boolsa(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)returnfalse;//若為正,則返回falsereturntrue;//否則返回true}voidperm(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);}}}intmain()//主函數{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 = ”elseif( i % a ==0)//判斷是否是每一行的行首,若是則輸出四個空格,保證輸出的格式優美printf(" ");if( i % a ==0)//判斷是否是行首,若是輸出制表符豎線,可與上一句寫到一塊兒printf("┃");if(( i +1)% a ==0)//判斷是否是行列式某一行的最后一個數printf("%2d",*( c + i ));elseprintf("%2d ",*( c + i ));//若不是行列式某一行的最后一個數則在數字后邊加一個空格if(( i +1)% a ==0)//判斷是否到達一行的行末printf("┃");if(( i +1)/ a == f /2&&( i +1)% a ==0)//判斷是否達到行列式中間一行的行末,輸出整個行列式的值printf(" = %d\n", sum);elseif(( i +1)% a ==0)//判斷是否到達行末輸出換行printf("\n");}printf("\n\n");printf("是否繼續?( 1 / 0 )\n");//提示是否退出scanf("%d",&e);n =0;//每次都將都將上一次的運行記錄消除sum=0;if( e ==1)goto u;//判斷是否推出elseif( e ==0)exit(0);}