对角矩阵压缩详解
首先我们要明白,什么是对角矩阵,他是对角矩阵是一个主对角线之外的元素皆为0的矩阵,也就是他是沿着主对角线左右扩展的矩阵,他的规律就在他的主对角线中。

这个一行最大个数为3个的对角矩阵,有一个公式为2*i+j-3,那么我们就要知道这个公式是怎么来的。
先看导出这种模式的代码
#include<bits/stdc++.h>
using namespace std;
int main(){
int b[200]={0};//给b这个数组从1到200可以看检查我们的答案
for(int i=1;i<=200;i++){
b[i-1]=i;
}
for(int i=1;i<=6;i++){
for(int j=1;j<=6;j++){
if(abs(i-j)<=1){
cout<<b[2*i+j-3]<<" ";
}else{
cout<<"0 ";
}
}
cout<<endl;
}
}
编译效果

如何导出公式
- 首先前面说了,对角矩阵的规律在其对角线中,那么我们先看这个对角矩阵总共有效的数字个数,从编译我们可以看出,一共16个,那么这16个有什么规律呢?
- 从图片中我们不难看出,一行3个,一共6行,但是注意,第一行左半部分是没有数字的,并且最后对角线的又半部分也没有数字,那么一共的数字就是3*i-2,我们设定i为矩阵的行数;
- 然后我们观察,找到对角线的数字个数,为1,4,7,10,13,16,我们拿出第三行看,7,当我们看这个7的时候,他的右边我们是不考虑的。所以,他右边也少一个数字,那么我们的对角线的规律也就是3*i-2;
- 这个公式是对角线的数字,现在我们不仅要知道对角线的数字,我们还需要知道这个对角线左右两边的个数,
- 那么我们不仅需要知道3*i-2我们还有知道3*i-2-1和3*i-2+1,现在我们的目的就是要给这3个公式合起来为一个式子,现在我们引用j。
- j为矩阵的列数,让j>=i-1且j<=i+1时打印j,而原来的3*i-2我们可以看成i+i+i+2,把其中的一个i用j代替,用j取3个数,i+1和i-1和i,这样我们就可以导出原有的公式2*i+j-2,那么为什么不是原始的公式2*i+j-3呢?是因为我们b是从b[0]开始的,所以第一个数是b[0],所以要在2*i+j-2的基础上-1,我们就导出了公式2*i+j-3
从简单公式进阶
现在为一行最多3个,那么如果是5个应该怎么改这个公式呢?
#include<bits/stdc++.h>
using namespace std;
int main(){
int b[200]={0};
for(int i=1;i<=200;i++){
b[i-1]=i;
}
for(int i=1;i<=6;i++){
for(int j=1;j<=6;j++){
if(abs(i-j)<=2&&i>1&&i<6){
cout<<b[4*i+j-6]<<" ";
}else{
if(abs(i-j)<=2&&i<=1){
cout<<b[4*i+j-5]<<" ";
}else if(abs(i-j)<=2&&i>=6){
cout<<b[4*i+j-7]<<" ";
}else{
cout<<"0 ";
}
}
}
cout<<endl;
}
cout<<endl;
}

- 首先在我们明白上面公式如何导出后,我们先导出对角线的数字,正常如果按照一行5个来算,一共的数字为5*i,然后我们看,每个对角线后存在2个我们不用的,就为5*i-2,但是第一行左边也有2个不用,就为5*i-4,现在分界点来了,在第二行,第二行中间数左半部分有部分没进入。
- 所以我们以第一行为分界点,当i>1时,左边一共少2个,右边一共少2个,所以总共比正常的5i少5个就为5*i-4
- 而从第一行以后到 i 行前就第二行少了一个,所以左边一个少3个,右边一共少2个,所以总共比正常少5个就为5*i-5。
- 然后引入 j ,现在的j和之间有一点不同点就是要j>=i-2且j<=i+2 然后把其中的一个i改为j,两个公司就变为4*i+j-4和4*i+j-5
- 同理,右边也有地方部分进入的,所以我们也要在右边做一个分界点,这个分界点就是6,那么和左边一样,当i==6时他也要在中间基础上少1,就是4*i+j-6
- 最后从b[0]开始上面两个公式各-1,公式变为4*i+j-5和4*i+j-6,4*i+j-7一行最多5个就结束了.
最终通用公式导出
当每行最多字符为7,矩阵边数为9时,编译运行

现在我们把每行最多的个数设定为x,每次改变x最后的效果.
7. 还是重复之前的步骤,先找出总共正常的数字个数为x*i
8. 然后找右边缺少个个数,为**(x-1)/2**
9. 然后划分分界点,当最终的 i 左边有部分进入,最终的 i 和左边没有进入也就是下图3个

和

和

- 先看中间的图的分界,他一共少了前面3+2+1个,那么他就是小了从1+···(x-1)/2,根据叠加,左边一共少了这些(x*x-1)/8,而右边少了(x-1)/2,所以中间部分的分界点的公式就是(x-1)*i+j-( x * x-1)/8-(x-1)/2-1, ( j 和-1)都和前面一样.
- 接下来导出上变分界,上方叠加是从(x-1)/2-(i-1)+``````(x-1),所以根据叠加公式为,(i*(x-i))/2,说以上方的公式就是,(x-1)*i+j-(x-1)/2-(i * (x-i))/2-1,(j和-1和之前一样)
- 最后看下半边界,左边缺少(xx-1)/8,而右边缺少从1+····(x-1)/2+i-10,根据叠加缺少((x-1)/2+i-10)((x-1)/2+i-11)/2,并且还缺少一个(x-1)/2,所以一共缺少(x-1) * i+j-((x-1)/2+i-10)*((x-1)/2+i-11)/2-(x * x-1)/8-(x-1)/2-1;
最后发一下写出的的代码
int x=7;
for(int i=1;i<=10;i++){
for(int j=1;j<=10;j++){
if(abs(i-j)<=(x-1)/2&&(x-1)/2-i<=0&&(x-1)/2+i<=10){
cout<<b[(x-1)*i+j-(x*x-1)/8-(x-1)/2-1]<<"\t";
}else{
if(abs(i-j)<=(x-1)/2&&(x-1)/2-i>0){
cout<<b[(x-1)*i+j-(x-1)/2-(i*(x-i))/2-1]<<"\t";
}else if(abs(i-j)<=(x-1)/2&&(x-1)/2+i>10){
cout<<b[(x-1)*i+j-((x-1)/2+i-10)*((x-1)/2+i-11)/2-(x*x-1)/8-(x-1)/2-1]<<"\t";
}else{
cout<<"0\t";
}
}
}
cout<<endl;
}
本文详细解析了对角矩阵的压缩方法,从基础的对角矩阵概念出发,逐步导出针对不同行数的对角矩阵的通用压缩公式,通过分析矩阵的结构特点,推导出公式2*i+j-3,并进一步扩展到不同宽度的对角矩阵的通用公式,阐述了公式变化的逻辑过程。

2161

被折叠的 条评论
为什么被折叠?



