123456789組成的3×3的矩陣的行列式最大的值是多少?
123456789怎樣運算等於1? - abccsss 的回答
假定每個數字只能出現一次。
Mathematica代碼
較簡潔Det/@N@Range@9~Permutations~{9}~ArrayReshape~{9!,3,3}//Max
較高效
Max@Table[Evaluate@Det@Quiet@Array[i[[3#+#2-3]],{3,3}],{i,Range@9~Permutations~{9}}]
以上用Matlab暴力破解(枚舉種情形),暫未輸出行列式相同的其他情形,貌似基本秒出。
max_det = 0;
init_perm = reshape(1:9, [3, 3]);
all_perms = perms(1:9);
for i = 1:size(all_perms, 1)
matrix = all_perms(i, :);
matrix = reshape(matrix, [3, 3]);
det_value = det(matrix);
if det_value &> max_det
max_det = det_value;
init_perm = matrix;
end
end
對於三階的窮舉,可以不用det函數會比較簡單:
p = reshape(perms(1:9),"",3,3);
M = max(sum(prod(p,2),3)-sum(prod(p,3),2));
並且如果用整數類型可以稍微快一些(sum和prod需要"native"參數)。不過上邊的方法有很多重複的情形。由於行列式交換行或列位置以及轉置都不會改變其絕對值大小,所以要計算的情況可以少很多。但是對於3階只算一次上邊的方法夠用了。
{Det[Partition[#~Join~{8,9},3]]/@Permutations@Range@7,Det[Partition[Insert[#,8,-4]~Append~9,3]]/@Permutations@Range@7}極少的優化……
話題的語言還少個Mathematica,就我來吧直接9!個結果存下來剛正面,0優化
Det[Partition[#, 3]] /@ Permutations[Range[9]] // Max
412
貼個毫無技術含量暴力程度max的python版。。。
import itertools
import time
def max_matrix():
begin = time.time()
elements = [1, 2, 3, 4, 5, 6, 7, 8, 9]
maxdet = 0
maxmat = []
for i in itertools.permutations(elements, 9):
det = i[0] * i[4] * i[8] + i[1] * i[5] * i[6] + i[2] * i[3] * i[7] - i[2] * i[4] * i[6] - i[1] * i[3] * i[8] - i[0] * i[5] * i[7]
if(det &> maxdet):
maxdet = det
maxmat = []
for j in range(0, 9):
maxmat.append(i[j])
print "|" + str(maxmat[0]) + " " + str(maxmat[1]) + " " + str(maxmat[2]) + "|"
print "|" + str(maxmat[3]) + " " + str(maxmat[4]) + " " + str(maxmat[5]) + "| = " + str(maxdet)
print "|" + str(maxmat[6]) + " " + str(maxmat[7]) + " " + str(maxmat[8]) + "|"
end = time.time()
print str(end - begin) + "s used."
if __name__ == "__main__":
max_matrix()
題目應該改成1 2 3 ...n^2組成n階行列式的最大值。並求最優解的時間複雜度才有意思。
C++版的暴力破解...最大值為412,總共36個解。
#include &
#include &
#include &
using namespace std;
inline int Determinant(const vector&
{
return v[0]*v[4]*v[8] + v[2]*v[3]*v[7] + v[1]*v[5]*v[6] - v[2]*v[4]*v[6] - v[0]*v[5]*v[7] - v[1]*v[3]*v[8];
}
int main()
{
vector&
int detValue = Determinant(vec);
vector&
vector&
while ( next_permutation(vec.begin(), vec.end()) )
{
int value = Determinant(vec);
if (detValue &< value)
{
detValue = value;
mat.assign(vec.begin(), vec.end());
result.clear();
result.push_back(mat);
}
else if (detValue == value)
{
mat.assign(vec.begin(), vec.end());
result.push_back(mat);
}
}
cout &<&< detValue &<&< endl;
for (const auto item : result)
{
for (const auto i : item)
cout &<&< i &<&< " ";
cout &<&< endl;
}
return 0;
}
把yellow的答案重排一下可得
9 4 23 8 6
5 1 7很容易看出思路了。
1.所有數按大小在斜率為-1的對角線上依次排開。(即:987在一條對角線,654在一條,321在一條)很容易看出這是讓正向數值最大的方法。2.對於反向的對角線,排除主對角線之外的任意兩個數之和相等,且乘積越大的,相應的主對角線元素越小。(也就是讓三個乘積的最大值最小,然後最大的結果再和最小的數相配這樣)但是以上方法僅限於1~9的3x3矩陣,對於其它的矩陣不一定適用。
因為顯然這種方法要求正向和負向都只有對角線(或平行於對角線),但是4x4的行列式就開始有拐彎了。。。然後,我感覺還有三個漏洞,一是貪心法不一定保證正向最大,也不一定保證反向最小,更不一定保證正反向之差最大。(不一定都是漏洞,可能有的是恆成立的)
但是我感覺對3x3的非負矩陣來說,貪心在多數情況下是可以拿到最大值的。PS:試了很多組數,都是這個解,然後又試了一組[1 2 3 4 5 6 7 8 100],顯然答案發生了變化,因為100的權值比8和7大太多,所以負向的時候直接就把2和1給了100。那麼這也就證明了貪心法確實有時候得不到最大值。#python2
from itertools import permutationsfrom numpy import reshapefrom numpy.linalg import detprint max(map(lambda m:det(reshape(m,(3,3))),permutations(xrange(1,10))))
結果:412想問一下,有不用計算機的解法嗎?
C++:
#include &
#include &
using namespace std;
int ans, a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int main() {
do
ans = max(ans, a[0] * (a[4] * a[8] - a[5] * a[7]) +
a[1] * (a[5] * a[6] - a[3] * a[8]) +
a[2] * (a[3] * a[7] - a[4] * a[6]));
while (next_permutation(a, a + 9));
printf("%d
", ans);
}
運行結果:
412
[1, 4, 8]
[7, 2, 6][5, 9, 3][1, 5, 7]
[8, 3, 6][4, 9, 2][1, 7, 5]
[4, 2, 9][8, 6, 3][1, 8, 4]
[5, 3, 9][7, 6, 2][2, 4, 9]
[7, 1, 5][6, 8, 3][2, 6, 7]
[9, 3, 5]
[4, 8, 1][2, 7, 6]
[4, 1, 8][9, 5, 3][2, 9, 4]
[6, 3, 8][7, 5, 1][3, 5, 9]
[8, 1, 4][6, 7, 2]
[3, 6, 8]
[9, 2, 4][5, 7, 1][3, 8, 6]
[5, 1, 7][9, 4, 2][3, 9, 5]
[6, 2, 7][8, 4, 1][4, 1, 8]
[9, 5, 3][2, 7, 6][4, 2, 9]
[8, 6, 3][1, 7, 5][4, 8, 1]
[2, 6, 7][9, 3, 5][4, 9, 2]
[1, 5, 7][8, 3, 6][5, 1, 7]
[9, 4, 2][3, 8, 6][5, 3, 9]
[7, 6, 2][1, 8, 4][5, 7, 1]
[3, 6, 8][9, 2, 4][5, 9, 3]
[1, 4, 8][7, 2, 6][6, 2, 7]
[8, 4, 1][3, 9, 5][6, 3, 8]
[7, 5, 1][2, 9, 4][6, 7, 2]
[3, 5, 9][8, 1, 4][6, 8, 3]
[2, 4, 9][7, 1, 5][7, 1, 5]
[6, 8, 3][2, 4, 9][7, 2, 6]
[5, 9, 3][1, 4, 8][7, 5, 1]
[2, 9, 4][6, 3, 8][7, 6, 2]
[1, 8, 4][5, 3, 9][8, 1, 4]
[6, 7, 2][3, 5, 9][8, 3, 6]
[4, 9, 2][1, 5, 7][8, 4, 1]
[3, 9, 5][6, 2, 7][8, 6, 3]
[1, 7, 5][4, 2, 9][9, 2, 4]
[5, 7, 1][3, 6, 8][9, 3, 5]
[4, 8, 1][2, 6, 7][9, 4, 2]
[3, 8, 6][5, 1, 7][9, 5, 3]
[2, 7, 6][4, 1, 8]計算機暴力窮舉;低端原始點的python代碼:a=[1,2,3,4,5,6,7,8,9]
def det(a):
i_1=a[0][0]*a[1][1]*a[2][2]
i_2=a[0][1]*a[1][2]*a[2][0]
i_3=a[0][2]*a[1][0]*a[2][1]
i_4=a[0][2]*a[1][1]*a[2][0]
i_5=a[0][1]*a[1][0]*a[2][2]
i_6=a[0][0]*a[1][2]*a[2][1]
f=i_1+i_2+i_3-i_4-i_5-i_6
return f
b=a[:]
n=0
for i_1 in b:
b_1=b[:]
b_1.remove(i_1)
for i_2 in b_1:
b_2=b_1[:]
b_2.remove(i_2)
for i_3 in b_2:
b_3=b_2[:]
b_3.remove(i_3)
for i_4 in b_3:
b_4=b_3[:]
b_4.remove(i_4)
for i_5 in b_4:
b_5=b_4[:]
b_5.remove(i_5)
for i_6 in b_5:
b_6=b_5[:]
b_6.remove(i_6)
for i_7 in b_6:
b_7=b_6[:]
b_7.remove(i_7)
for i_8 in b_7:
b_8=b_7[:]
b_8.remove(i_8)
for i_9 in b_8:
c=[[i_1,i_2,i_3],[i_4,i_5,i_6],[i_7,i_8,i_9]]
if det(c) &> n:
n = det(c)
print(n)
for i_1 in b:
b_1=b[:]
b_1.remove(i_1)
for i_2 in b_1:
b_2=b_1[:]
b_2.remove(i_2)
for i_3 in b_2:
b_3=b_2[:]
b_3.remove(i_3)
for i_4 in b_3:
b_4=b_3[:]
b_4.remove(i_4)
for i_5 in b_4:
b_5=b_4[:]
b_5.remove(i_5)
for i_6 in b_5:
b_6=b_5[:]
b_6.remove(i_6)
for i_7 in b_6:
b_7=b_6[:]
b_7.remove(i_7)
for i_8 in b_7:
b_8=b_7[:]
b_8.remove(i_8)
for i_9 in b_8:
c=[[i_1,i_2,i_3],[i_4,i_5,i_6],[i_7,i_8,i_9]]
if det(c) == n:
print(c[0])
print(c[1])
print(c[2])
print()
import itertools
import numpy as np
maxDet = max( map( np.linalg.det, map( lambda x:np.array(x).reshape(3,3), itertools.permutations(range(1,10),9) ) ) )
print(maxDet)
沒有matlab快,這是為什麼?
東施效顰一下 @鄒沖
#include&
#include&
#include&
#include&
#include&
using namespace std;
int main()
{
int temp; int target = INT_MIN; int target_marix[9];
int numbers[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
while (next_permutation(numbers, numbers + 9))
{
temp = numbers[0] * numbers[4] * numbers[8] + numbers[3] * numbers[7] * numbers[2] + numbers[1] * numbers[5] * numbers[6]- (numbers[2] * numbers[4] * numbers[6] + numbers[1] * numbers[3] * numbers[8] + numbers[5] * numbers[7] * numbers[0]);
if (target &< temp)
{
target = temp;
for (int i = 0; i &< 9; i++)
{
target_marix[i] = numbers[i];
}
}
}
for (int i = 0; i &< 9; i++)
{
cout &<&< target_marix[i] &<&< " ";
if ((i + 1) % 3 == 0)
cout &<&< endl;
}
}
前面已經有了python,c和MMA的代碼了,我來一發matlab的吧
p=perms(1:9);
[n,~]=size(p);
z=zeros(n,1);
for i=1:n
z(i)=det(reshape(p(i,:),3,3));
end
max(z)
id=find(z==max(z));
for i=1:length(id)
disp(reshape(p(id(i),:),3,3));
end
結果最大值是412,最大值點如下:
9 2 4 5 7 1 3 6 89 3 5
4 8 1 2 6 79 4 2
3 8 6 5 1 79 5 3
2 7 6 4 1 88 1 4
6 7 2 3 5 98 3 6
4 9 2 1 5 78 4 1
3 9 5 6 2 78 6 3
1 7 5 4 2 97 1 5
6 8 3 2 4 97 2 6
5 9 3 1 4 87 5 1
2 9 4 6 3 86 2 7
8 4 1 3 9 56 3 8
7 5 1 2 9 46 7 2
3 5 9 8 1 46 8 3
2 4 9 7 1 55 1 7
9 4 2 3 8 65 7 1
3 6 8 9 2 45 9 3
1 4 8 7 2 64 2 9
8 6 3 1 7 54 1 8
9 5 3 2 7 64 8 1
2 6 7 9 3 54 9 2
1 5 7 8 3 63 5 9
8 1 4 6 7 23 9 5
6 2 7 8 4 13 8 6
5 1 7 9 4 23 6 8
9 2 4 5 7 12 4 9
7 1 5 6 8 32 9 4
6 3 8 7 5 12 7 6
4 1 8 9 5 32 6 7
9 3 5 4 8 11 5 7
8 3 6 4 9 21 4 8
7 2 6 5 9 31 7 5
4 2 9 8 6 3一共是33個。少的那三個估計來自於MATLAB的計算誤差,懶得改了。推薦閱讀:
※如何使用MATLAB求解logistic模型的參數?
※為什麼工程上的模擬模擬都用matlab 而不是mathematica?
※怎麼用matlab 2017b的APP Designer?
※Eigen 矩陣運算庫在實際項目中的使用情況如何?
※用matlab繪製電場線和等勢面如何做?
TAG:Python | MATLAB | WolframMathematica | 線性代數 |