using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
namespace
Determinant
{
class
Program
{
static
void
Main(
string
[] args)
{
//
Console.WriteLine(D.SwitchCount(new int[] { 3, 2, 5, 1, 4 }));
//
D.PermutationGen pg = new D.PermutationGen(4);
//
pg.FastIteration = true;
//
foreach (var p in pg)
//
{
//
Console.WriteLine(pg.PermutationToString(p));
//
}
D d1
=
new
D(
3
);
d1.Data[
0
,
0
]
=
1
;
d1.Data[
0
,
1
]
=
2
;
d1.Data[
0
,
2
]
=
-
4
;
d1.Data[
1
,
0
]
=
-
2
;
d1.Data[
1
,
1
]
=
2
;
d1.Data[
1
,
2
]
=
1
;
d1.Data[
2
,
0
]
=
-
3
;
d1.Data[
2
,
1
]
=
4
;
d1.Data[
2
,
2
]
=
-
2
;
Console.WriteLine(d1.Value);
D d2
=
new
D(
2
);
d2.Data[
0
,
0
]
=
3
;
d2.Data[
0
,
1
]
=
12
;
d2.Data[
1
,
0
]
=
2
;
d2.Data[
1
,
1
]
=
1
;
Console.WriteLine(d2.Value);
Console.ReadKey();
}
}
public
class
D
{
///
<summary>
///
计算1-n的一个全排列的逆序数
///
</summary>
///
<param name="permutation">
a permutation of 1-permutation.Length
</param>
///
<returns></returns>
public
static
int
SwitchCount(
int
[] permutation)
{
int
count
=
0
;
if
(permutation
==
null
||
permutation.Length
==
0
)
throw
new
ArgumentException(
"
输入不能为空
"
,
"
permutation
"
);
if
(permutation.Length
==
1
)
{
return
0
;
}
for
(
int
i
=
0
; i
<
permutation.Length; i
++
)
{
if
(permutation[i]
<
1
||
permutation[i]
>
permutation.Length)
throw
new
ArgumentException(
"
只计算1-n的排列的逆序数
"
);
}
for
(
int
i
=
0
; i
<
permutation.Length; i
++
)
{
for
(
int
j
=
i
+
1
; j
<
permutation.Length; j
++
)
{
if
(permutation[i]
>
permutation[j]) count
++
;
else
if
(permutation[i]
==
permutation[j])
throw
new
ArgumentException(String.Format(
"
数字{0}重复出现在位置{1}和{2}
"
, permutation[i], i, j),
"
permutation
"
);
}
}
return
count;
}
double
[,] data;
int
n;
PermutationGen pg;
public
D(
int
rank)
{
if
(rank
<
2
)
throw
new
ArgumentException(
"
Rank is at least 2.
"
);
n
=
rank;
data
=
new
double
[rank, rank];
data.Initialize();
}
public
double
[,] Data
{
get
{
return
data;
}
}
public
double
Value
//
calculate the value form the data given
{
get
{
double
v
=
0
;
if
(pg
==
null
)
{
pg
=
new
PermutationGen(n);
}
foreach
(var p
in
pg)
{
double
u
=
1
;
for
(
int
i
=
0
; i
<
n; i
++
)
{
//
固定行,选列
u
*=
data[i, p[i]
-
1
];
}
u
*=
((SwitchCount(p)
&
1
)
==
1
?
-
1
:
1
);
v
+=
u;
}
return
v;
}
}
public
class
PermutationGen : IEnumerable
<
int
[]
>
{
int
[] p, t, f;
int
len;
StringBuilder pString;
public
bool
ReturnNewPermutation
{
get
;
set
;
}
public
bool
FastIteration
{
get
;
set
;
}
public
PermutationGen(
int
length)
{
len
=
length;
p
=
new
int
[length];
t
=
new
int
[length];
//
尚未被使用的数字
f
=
new
int
[length
+
1
];
for
(
int
i
=
len; i
>=
0
; i
--
)
//
最前面两个元素不用
{
f[i]
=
Factorial(i);
}
}
public
int
Count
{
get
{
return
f[len];
}
}
///
<summary>
///
///
</summary>
///
<param name="id">
1至len
</param>
///
<returns></returns>
public
int
[] GetPermutation(
int
id)
{
if
(id
>=
f[len]
||
id
<
0
)
throw
new
ArgumentException(
"
1<=id<=len!
"
);
for
(
int
i
=
0
; i
<
len; i
++
)
//
所有数字都未被使用
{
t[i]
=
i
+
1
;
}
int
r, n, m
=
id;
for
(
int
i
=
0
; i
<
len; i
++
)
{
n
=
Math.DivRem(m, f[len
-
i
-
1
],
out
r);
p[i]
=
GetUnusedNumberN(n
+
1
);
m
=
r;
}
return
p;
}
public
string
PermutationToString(
int
[] p)
{
int
len
=
p.Length;
if
(pString
==
null
)
{
pString
=
new
StringBuilder(len
*
3
);
}
pString.Length
=
0
;
pString.Append(p[
0
]);
for
(
int
i
=
1
; i
<
len; i
++
)
{
pString.Append(
"
,
"
);
pString.Append(p[i]);
}
return
pString.ToString();
}
public
string
GetPermutationString()
{
return
PermutationToString(p);
}
public
static
int
Factorial(
int
n)
{
int
result
=
1
;
for
(
int
i
=
n; i
>
1
; i
--
)
{
result
*=
i;
}
return
result;
}
///
<summary>
///
返回第n个未被使用的元素
///
</summary>
///
<param name="n"></param>
///
<returns></returns>
int
GetUnusedNumberN(
int
n)
{
int
count
=
0
;
for
(
int
i
=
0
; i
<
len; i
++
)
{
if
(t[i]
!=
0
)
{
count
++
;
if
(count
==
n)
{
int
q
=
t[i];
t[i]
=
0
;
//
返回即被使用
return
q;
}
}
}
return
0
;
//
没有足够的剩余元素
}
///
<summary>
///
return the smallest positive integer that is not included in the n elements of array starting for start
///
</summary>
int
GetNextSmallest(
int
[] array,
int
start,
int
n,
int
searchStart)
{
int
i;
for
(i
=
searchStart; i
<=
searchStart
+
n; i
++
)
{
int
j;
for
(j
=
start; j
<
n; j
++
)
{
if
(array[j]
==
i)
break
;
}
if
(j
==
n)
{
return
i;
}
}
return
0
;
//
impossible, but required by grammar
}
#region
IEnumerable<int[]> 成员
public
IEnumerator
<
int
[]
>
GetEnumerator()
{
if
(FastIteration)
{
for
(
int
i
=
0
; i
<
len; i
++
)
{
p[i]
=
i
+
1
;
}
for
(
int
i
=
0
; i
<
f[len]
-
1
; i
++
)
//
返回第0号到倒数第二个排列
{
yield
return
ReturnNewPermutation
?
p.Clone()
as
int
[] : p;
//
每次迭代构造下次应当返回的排列
for
(
int
j
=
len
-
1
; j
>
0
; j
--
)
{
if
(i
/
f[j]
!=
(i
+
1
)
/
f[j])
{
//
set p at level j
int
k
=
len
-
j
-
1
;
//
convert to p index
p[k]
=
GetNextSmallest(p,
0
, k, p[k]
+
1
);
k
++
;
while
(k
<
len)
{
p[k]
=
GetNextSmallest(p,
0
, k,
1
);
k
++
;
}
break
;
}
}
}
yield
return
ReturnNewPermutation
?
p.Clone()
as
int
[] : p;
}
else
{
if
(ReturnNewPermutation)
{
for
(
int
i
=
0
; i
<
f[len]; i
++
)
{
yield
return
GetPermutation(i).Clone()
as
int
[];
}
}
else
{
for
(
int
i
=
0
; i
<
f[len]; i
++
)
{
yield
return
GetPermutation(i);
}
}
}
}
#endregion
#region
IEnumerable 成员
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return
GetEnumerator();
}
#endregion
}
}
}