六角幻方(高斯消元法求解)

2023-11-20 12:59

本文主要是介绍六角幻方(高斯消元法求解),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

看了网上很多都是用dfs解决的,于是自己就写了一篇用高斯消元法的解决方法

问题描述

把 1 2 3 … 19 共19个整数排列成六角形状,如下:

要求每个直线上的数字之和必须相等。共有15条直线哦!

再给点线索吧!我们预先填好了2个数字,第一行的头两个数字是:15 13,参见下图,黄色一行为所求。【p1.png】

请你填写出中间一行的5个数字。数字间用空格分开。

这是一行用空格分开的整数,请通过浏览器提交答案,不要填写任何多余的内容(比如说明性的文字等)

解法

把15条直线看成是15条方程,每一个圆看成一个未知数,且未知数的系数为1即六角幻方对应的未知数:

	 x0  x1  x2 x3  x4  x5  x6 x7  x8  x9  x10  x11x12  x13  x14  x15x16  x17  x18 

x0+x1+x2=38
x3+x4+x5+x6=38
x7+x8+x9+x10+x11=38
x12+x13+x14+x15=38
x16+x17+x18=38
…太多了,我就不写了

代码

/*六角幻方的各个数的下标 x0  x1  x2 x3  x4  x5  x6 x7  x8  x9  x10  x11x12  x13  x14  x15x16  x17  x18 
*/ #include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
using namespace std;
#define N 19
#define M 15
int am[M][N],bm[M],col[N],vi[N],ans[N],ans2[N];
int in[M][7]={ 
{0,1,2,-1},	 //-1作为结尾标志
{3,4,5,6,-1},
{7,8,9,10,11,-1},
{12,13,14,15,-1},
{16,17,18,-1},
{0,3,7,-1},
{1,4,8,12,-1},
{2,5,9,13,16,-1},
{6,10,14,17,-1},
{11,15,18,-1},
{2,6,11,-1},
{1,5,10,15,-1},
{0,4,9,14,18,-1},
{3,8,13,17,-1},
{7,12,16,-1}
};
void init(){memset(am,0,sizeof(am));for(int i=0;i<M;i++){for(int j=0;in[i][j]!=-1;j++){am[i][in[i][j]]=1;}bm[i]=38;/*由于1到19的累加和为109,通过对图中随便构成5条不相交的直线,即  {0,1,2,-1},{3,4,5,6,-1},{7,8,9,10,11,-1},{12,13,14,15,-1},{16,17,18,-1},作为5条直线,且由题意可知每条直线总和相等,所以109/5=38,即每条直线必定和为38*/ } for(int i=0;i<N;i++)col[i]=i;//因为高斯消元中有交换列的处理,所以要标志i列为那个未知数 
}
void r_swap(int i,int j){if(i==j) return ;for(int k=0;k<N;k++){swap(am[i][k],am[j][k]);}swap(bm[i],bm[j]);
}
void c_swap(int k){int i;for(i=k;i<N;i++){if(am[k][i]!=0)break;}if(k==i || i>=N) return ;for(int j=0;j<M;j++){swap(am[j][k],am[j][i]);}swap(col[k],col[i]);
}
int gcd(int a,int b){return b==0?a:gcd(b,a%b);
}
void xiao_yuan(int k,int j){int u=am[k][k],v=am[j][k];if(u==0||v==0) return ;int g=gcd(u,v);for(int i=0;i<N;i++)//必须从0开始,因为这一行要乘以u/g,且从0开始的元素并不一定为0 {am[j][i]=(u*am[j][i]-v*am[k][i])/g;/*原本为am[j][i]=am[j][i]-v/u*am[k][i]);但是v/u可能存在精度误差,所以解决这个问题最好是在计算过程中得出的都是整数将 am[j][i]=am[j][i]-v/u*am[k][i])两边乘以u,得 u*am[j][i]=u*am[j][i]-v*am[k][i]由于将方程组中的某一行两边同时乘以一个数,并不会影响方程组的求解,所以可以令am[j][i]=u*am[j][i]=u*am[j][i]-v*am[k][i],即 am[j][i]=u*am[j][i]-v*am[k][i]由于 u*am[j][i]-v*am[k][i]可能结果很大,所以除以u和v的最大公约数最终得到 am[j][i]=(u*am[j][i]-v*am[k][i])/g的形式 */ }bm[j]=(u*bm[j]-v*bm[k])/g;//此处跟 am[j][i]=(u*am[j][i]-v*am[k][i])/g同理 
}
void show(){/*static int cnt=0;printf("第%d次消元\n",cnt);*/printf("最终消元结果:\n");for(int i=0;i<N;i++){printf("%5d",col[i]);}printf("   bm\n");for(int i=0;i<(N+1)*5;i++)printf("%c",'-');printf("\n");for(int i=0;i<M;i++){for(int j=0;j<N;j++)printf("%5d",am[i][j]);printf("%5d\n",bm[i]);}printf("\n\n");
}
void guass(){for(int i=0;i<M;i++){//show();for(int j=i;j<M;j++){if(am[j][i]!=0){r_swap(i,j);//找到不为零的行就交换 break;}}c_swap(i);//如果没有找到不为零的行,就找不为零的列,然后交换 for(int j=0;j<M;j++){if(j!=i)xiao_yuan(i,j);}			}
}
void output(){//static int cnt=1;//printf("no.%d\n",cnt++); if(ans2[0]!=15||ans2[1]!=13)//不满足题目要求的结果不显示 return ;printf("%*c%2d  %2d  %2d%*c\n\n",4,' ',ans2[0],ans2[1],ans2[2],6,' ');printf("%*c%2d  %2d  %2d  %2d%*c\n\n",2,' ',ans2[3],ans2[4],ans2[5],ans2[6],3,' ');printf("%2d  %2d  %2d  %2d  %2d\n\n",ans2[7],ans2[8],ans2[9],ans2[10],ans2[11]);printf("%*c%2d  %2d  %2d  %2d%*c\n\n",2,' ',ans2[12],ans2[13],ans2[14],ans2[15],3,' ');printf("%*c%2d  %2d  %2d%*c\n\n\n",4,' ',ans2[16],ans2[17],ans2[18],6,' ');//getchar();
}
void check(){for(int i=11;i>=0;i--){int t=0;for(int j=12;j<N;j++){t+=am[i][j]*ans[j];}t=(bm[i]-t)/am[i][i];if(t<1||t>N)return ;for(int j=i+1;j<N;j++){/*判断填进去的数字是否有重复,此处其实可以使用set树,然后查找,即时间复杂度为log2(N),但是这里N=19,运算量不大,所以不使用该方法,有兴趣的小伙伴可以自己做一做 */ if(t==ans[j])return ;			}ans[i]=t;}for(int i=0;i<N;i++){ans2[col[i]]=ans[i];//将结果放回第i列对应的未知数内 }output();
}
void f(int *ans,int k){if(k<12)//由于最后求出的行最简形矩阵只有12行,所以另外7未知数要事先填进去 {check();return ;}for(int i=1;i<=N;i++){bool flag=true;for(int j=k+1;j<N;j++){if(i==ans[j]){flag=false;break;}}if(flag){ans[k]=i; f(ans,k-1);}}
}
int main(){init();guass();show();f(ans,18);return 0;
}

结果

在这里插入图片描述

这篇关于六角幻方(高斯消元法求解)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/394783

相关文章

HDU 5833 高斯消元

n个数,任选>=1个数相乘,使得乘积是完全平方数。 其实就是开关,控制灯泡。 数 ----第i个质因子p的个数%2  = {1 , 0} == 开关----第i个灯泡 = {开 , 关} 最后使得所有灯泡都是灭着的方案数 = 2^自由变元个数   全部关着的情况     ==   一个数也不选   应省去 import java.io.BufferedReader;

2024 年高教社杯全国大学生数学建模竞赛题目——2024 年高教社杯全国大学生数学建模竞赛题目的求解

2024 年高教社杯全国大学生数学建模竞赛题目 (请先阅读“ 全国大学生数学建模竞赛论文格式规范 ”) 2024 年高教社杯全国大学生数学建模竞赛题目 随着城市化进程的加快、机动车的快速普及, 以及人们活动范围的不断扩大,城市道 路交通拥堵问题日渐严重,即使在一些非中心城市,道路交通拥堵问题也成为影响地方经 济发展和百姓幸福感的一个“痛点”,是相关部门的棘手难题之一。 考虑一个拥有知名景区

基于SA模拟退火算法的多车辆TSP问题求解matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述        基于SA模拟退火算法的多车辆TSP问题求解matlab仿真,三个车辆分别搜索其对应的最短路径,仿真后得到路线规划图和SA收敛曲线。 2.测试软件版本以及运行结果展示 MATLAB2022A版本运行 (完整程序运行后无水印)

OpenGL/GLUT实践:流体模拟——数值解法求解Navier-Stokes方程模拟二维流体(电子科技大学信软图形与动画Ⅱ实验)

源码见GitHub:A-UESTCer-s-Code 文章目录 1 实现效果2 实现过程2.1 流体模拟实现2.1.1 网格结构2.1.2 数据结构2.1.3 程序结构1) 更新速度场2) 更新密度值 2.1.4 实现效果 2.2 颜色设置2.2.1 颜色绘制2.2.2 颜色交互2.2.3 实现效果 2.3 障碍设置2.3.1 障碍定义2.3.2 障碍边界条件判定2.3.3 障碍实现2.3.

JD 1147:Jugs(一种用最少步骤求解的方法)

OJ题目:click here~~ 题目分析:九度上这道没有要求最少步数,只要得到最后结果即可AC , bfs , dfs都行。最少步骤的方法肯定也能AC啦,分析如下。 输入的三个数:a,b,n;> 由题不定方程ax+by=n必定有解> 如果b=n,则fill B即可,否则用试探法求出这样的两组解(a1,b1)及(a2,b2),其中a1 >0,b1<0;a1是满足方程的最小正整数;a2

【2024全国大学生数学建模竞赛】B题 模型建立与求解(含代码与论文)

目录 1问题重述1.1问题背景1.2研究意义1.3具体问题 2总体分析3模型假设4符号说明(等四问全部更新完再写)5模型的建立与求解5.1问题一模型的建立与求解5.1.1问题的具体分析5.1.2模型的准备 目前B题第一问的详细求解过程以及对应论文部分已经完成! - 晚上7-8点之前第二问完成 - 明天中文之前全部写完 按照提交论文的格式进行撰写!完整版请看文章最后!

Java 快速求解x的x次幂结果为10

1.问题描述 如果x的x次幂结果为10(如图所示),你能计算出x的近似值吗? 显然,这个值是介于2和3之间的一个数字。 可以使用牛顿迭代公式进行求解,因为是逼近算法可以大大减少运算次数 public static void main(String[] args) {int i = 0;double x1 = 2.5;while (true) {i++;//x^x - 10 = 0//这一步

最值求解 | 管理类联考数学专项

日期内容2024.9.5新建2024.9.6曦曦求最值完结 实数求最值至少至多抽屉原理工程问题线性规划一次性绝对值求最值 参考: b站跟着曦曦老师玩转【最值】

2024数学建模国赛A题详细思路:基于空间几何运动学和优化模型matlab求解

2024数学建模国赛A题“板凳龙”闹元宵 2024高教社杯数学建模竞赛A题B题C题D题E题完整成品文章和全部问题的解题代码完整版本更新如下:https://www.yuque.com/u42168770/qv6z0d/rytbc1nelty1mu4o % 定义常量L_head = 3.41; % 龙头长度(米)L_body = 2.20; % 龙身长度(米)spiral_pitch =

清华MEM作业-利用管理运筹学的分析工具slover求解最优解的实现 及 通过使用文件或者套节字来识别进程的fuser命令

一、清华MEM作业-利用管理运筹学的分析工具slover求解最优解的实现         最近又接触了一些线性求解的问题,以前主要都是在高中数学里接触到,都是使用笔算,最后通过一些函数式得出最小或者最大值,最近的研究生学业上接触到了一个Excel solver分析工具,对这种线性求最优解的问题感觉使用起来真是得心应手。在使用这个工具前,EXCEL里需要先装上solver工具,装起来很也简单,网上