【回溯】B027_LQ_六角幻方 四阶幻方 九宫幻方 反幻方 魔方状态 纸牌三角形(恶心的剪枝)

本文主要是介绍【回溯】B027_LQ_六角幻方 四阶幻方 九宫幻方 反幻方 魔方状态 纸牌三角形(恶心的剪枝),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、六角幻方

把 1、2、3 … 19 共 19 个整数排列成六角形状,如下:
在这里插入图片描述
要求每个直线上的数字之和必须相等,共有 15 条 直线哦!

再给点线索吧!我们预先填好了 2 个数字,第一行的头两个数字是:15、13,如图。
在这里插入图片描述
请你填写出黄色一行的 5 个数字。数字间用空格分开

方法一:深搜+剪枝

思路

真的恶心,

#include<bits/stdc++.h>
using namespace std;
int a[20]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
int A[19], vis[19];
void dfs(int i) {if (i==7 && 28+A[2] != A[3]+A[4]+A[5]+A[6]) return;if (i==8 && 28+A[2] != A[0]+A[3]+A[7]) return;if (i==12 && (28+A[2] != A[7]+A[8]+A[9]+A[10]+A[11] || 28+A[2] != A[2]+A[6]+A[11])) return;if (i==13 && 28+A[2] != A[1]+A[4]+A[8]+A[12]) return;if (i==16 && (28+A[2] != A[12]+A[13]+A[14]+A[15] || 28+A[2] != A[5]+A[10]+A[15])) return;if (i==17 && (28+A[2] != A[2]+A[5]+A[9]+A[13]+A[16] || 28+A[2]!=A[7]+A[12]+A[16])) return;if (i==18 && (28+A[2] != A[6]+A[10]+A[14]+A[17] || 28+A[2] != A[3]+A[8]+A[13]+A[17])) return;if (i==19 && 28+A[2] == A[16]+A[17]+A[18]) {for (int k=7; k<=11; k++) printf("%d ", A[k]);return;}for (int j=1; j<20; j++) {if (vis[j]) continue;vis[j]=1;A[i]=a[j-1];dfs(i+1);vis[j]=0;}
}
int main() {memset(vis, 0, sizeof vis);A[0]=15, A[1]=13; vis[13]=vis[15]=1;dfs(2);return 0;
}
二、四阶幻方

把1~16的数字填入4x4的方格中,使得行、列以及两个对角线的和都相等,满足这样的特征时称为:四阶幻方。

四阶幻方可能有很多方案。如果固定左上角为1,请计算一共有多少种方案。

比如:
1 2 15 16
12 14 3 5
13 7 10 4
8 11 6 9以及:
1 12 13 8
2 14 7 11
15 3 10 6
16 5 4 9
就可以算为两种不同的方案

代码类似,需要恶心的剪枝…

#include<bits/stdc++.h>
using namespace std;
int ans, A[17], vis[17];void dfs(int i) {if (i==8 && A[0]+A[1]+A[2]+A[3] != A[4]+A[5]+A[6]+A[7]) return;if (i==12 && A[4]+A[5]+A[6]+A[7] != A[8]+A[9]+A[10]+A[11]) return;if (i==13 && (A[8]+A[9]+A[10]+A[11] != A[0]+A[4]+A[8]+A[12] || A[8]+A[9]+A[10]+A[11] != A[3]+A[6]+A[9]+A[12])) return;if (i==14 && A[8]+A[9]+A[10]+A[11] != A[1]+A[5]+A[9]+A[13]) return;if (i==15 && A[8]+A[9]+A[10]+A[11] != A[2]+A[6]+A[10]+A[14]) return;if (i==16) {int s1=A[8]+A[9]+A[10]+A[11], s2=A[12]+A[13]+A[14]+A[15], s3=A[3]+A[7]+A[11]+A[15], s4=A[0]+A[5]+A[10]+A[15];if (s1!=s2 || s1!=s3 || s1!=s4) return;ans++;}for (int next=1; next<17; next++) if (!vis[next]) {vis[next]=1, A[i]=next;dfs(i+1);vis[next]=0;}
}
int main() {std::ios::sync_with_stdio(false);vis[1]=1;A[0]=1;dfs(1);cout << ans;return 0;
}

在这里插入图片描述

三、九宫幻方

小明最近在教邻居家的小朋友小学奥数,而最近正好讲述到了三阶幻方这个部分,三阶幻方指的是将1~9不重复的填入一个3*3的矩阵当中,使得每一行、每一列和每一条对角线的和都是相同的。

三阶幻方又被称作九宫格,在小学奥数里有一句非常有名的口诀:“二四为肩,六八为足,左三右七,戴九履一,五居其中”,通过这样的一句口诀就能够非常完美的构造出一个九宫格来。

4 9 2
3 5 7
8 1 6

有意思的是,所有的三阶幻方,都可以通过这样一个九宫格进行若干镜像和旋转操作之后得到。现在小明准备将一个三阶幻方(不一定是上图中的那个)中的一些数抹掉,交给邻居家的小朋友来进行还原,并且希望她能够判断出究竟是不是只有一个解。

而你呢,也被小明交付了同样的任务,但是不同的是,你需要写一个程序~

输入
输入仅包含单组测试数据。
每组测试数据为一个3*3的矩阵,其中为0的部分表示被小明抹去的部分。
对于100%的数据,满足给出的矩阵至少能还原出一组可行的三阶幻方。
输出
如果仅能还原出一组可行的三阶幻方,则将其输出,否则输出“Too Many”(不包含引号)

样例输入
0 7 2
0 5 0
0 3 0
样例输出
6 7 2
1 5 9
8 3 4
#include<bits/stdc++.h>
using namespace std;int ans, A[10], put[10], bk[10], B[10];
void dfs(int i) {if (i==7 && A[1]+A[2]+A[3]!=A[4]+A[5]+A[6]) return;if (i==8 && (A[4]+A[5]+A[6]!=A[1]+A[4]+A[7] || A[4]+A[5]+A[6]!=A[3]+A[5]+A[7])) return;if (i==9 && A[2]+A[5]+A[8]!=A[4]+A[5]+A[6]) return;if (i==10 && A[7]+A[8]+A[9]==A[2]+A[5]+A[8] && A[7]+A[8]+A[9]==A[1]+A[5]+A[9]) {ans++;for (int j=1; j<10; j++) B[j]=A[j];return;}if (put[i]) {dfs(i+1); } else {for (int j=1; j<10; j++) if (!bk[j]) {bk[j]=1, A[i]=j;dfs(i+1);bk[j]=0;}}
}
int main() {std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);for (int i=1; i<=9; i++) {cin>>A[i];if (A[i]>0) put[i]=true;}dfs(1);if (ans==1) {for (int i=1; i<=9; i++) {cout << B[i] << ' ';if (i%3==0) cout << '\n';}} else {cout << "Too Many";}return 0;
}
四、反幻方

我国古籍很早就记载着

2 9 4 
7 5 3 
6 1 8 

这是一个三阶幻方。每行每列以及对角线上的数字相加都相等。
下面考虑一个相反的问题。
可不可以用 1~9 的数字填入九宫格,使得:每行每列每个对角线上的数字和都互不相等呢?
这应该能做到。
比如:

9 1 2 
8 4 3 
7 5 6 

你的任务是搜索所有的三阶反幻方。并统计出一共有多少种。旋转或镜像算同一种。 比如:

9 1 2     7 8 9     2 1 9 
8 4 3     5 4 1     3 4 8 
7 5 6     6 3 2     6 5 7 

3120

{//答案是int row1 = m[0]+m[1]+m[2];int row2 = m[3]+m[4]+m[5];int row3 = m[6]+m[7]+m[8];int col1 = m[0]+m[3]+m[6];int col2 = m[1]+m[4]+m[7];int col3 = m[2]+m[5]+m[8];int xie1 = m[0]+m[4]+m[8];int xie2 = m[2]+m[4]+m[6];int[] p = {row1,row2,row3,col1,col2,col3,xie1,xie2};for(int i=0; i<p.length; ++i)for(int j=i+1; j<p.length; ++j){if(p[i]==p[j])return;}count++;return;
}
五、魔方状态

二阶魔方就是只有2层的魔方,只由8个小块组成。如图所示。

小明很淘气,他只喜欢3种颜色,所有把家里的二阶魔方重新涂了颜色,如下:
前面:橙色、右面:绿色、上面:黄色、左面:绿色、下面:橙色、后面:黄色
请你计算一下,这样的魔方被打乱后,一共有多少种不同的状态。
如果两个状态经过魔方的整体旋转后,各个面的颜色都一致,则认为是同一状态。

六、纸牌三角形

A,2,3,4,5,6,7,8,9 共9张纸牌排成一个正三角形(A按1计算)。要求每个边的和相等。
下图就是一种排法这样的排法可能会有很多。
如果考虑旋转、镜像后相同的算同一种,一共有多少种不同的排法呢?

对结果除以 3 再除以 2

这篇关于【回溯】B027_LQ_六角幻方 四阶幻方 九宫幻方 反幻方 魔方状态 纸牌三角形(恶心的剪枝)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

MySQL 中的服务器配置和状态详解(MySQL Server Configuration and Status)

《MySQL中的服务器配置和状态详解(MySQLServerConfigurationandStatus)》MySQL服务器配置和状态设置包括服务器选项、系统变量和状态变量三个方面,可以通过... 目录mysql 之服务器配置和状态1 MySQL 架构和性能优化1.1 服务器配置和状态1.1.1 服务器选项

linux进程D状态的解决思路分享

《linux进程D状态的解决思路分享》在Linux系统中,进程在内核模式下等待I/O完成时会进入不间断睡眠状态(D状态),这种状态下,进程无法通过普通方式被杀死,本文通过实验模拟了这种状态,并分析了如... 目录1. 问题描述2. 问题分析3. 实验模拟3.1 使用losetup创建一个卷作为pv的磁盘3.

Java实现状态模式的示例代码

《Java实现状态模式的示例代码》状态模式是一种行为型设计模式,允许对象根据其内部状态改变行为,本文主要介绍了Java实现状态模式的示例代码,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来... 目录一、简介1、定义2、状态模式的结构二、Java实现案例1、电灯开关状态案例2、番茄工作法状态案例

通过prometheus监控Tomcat运行状态的操作流程

《通过prometheus监控Tomcat运行状态的操作流程》文章介绍了如何安装和配置Tomcat,并使用Prometheus和TomcatExporter来监控Tomcat的运行状态,文章详细讲解了... 目录Tomcat安装配置以及prometheus监控Tomcat一. 安装并配置tomcat1、安装

Linux之进程状态&&进程优先级详解

《Linux之进程状态&&进程优先级详解》文章介绍了操作系统中进程的状态,包括运行状态、阻塞状态和挂起状态,并详细解释了Linux下进程的具体状态及其管理,此外,文章还讨论了进程的优先级、查看和修改进... 目录一、操作系统的进程状态1.1运行状态1.2阻塞状态1.3挂起二、linux下具体的状态三、进程的

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

hdu1565(状态压缩)

本人第一道ac的状态压缩dp,这题的数据非常水,很容易过 题意:在n*n的矩阵中选数字使得不存在任意两个数字相邻,求最大值 解题思路: 一、因为在1<<20中有很多状态是无效的,所以第一步是选择有效状态,存到cnt[]数组中 二、dp[i][j]表示到第i行的状态cnt[j]所能得到的最大值,状态转移方程dp[i][j] = max(dp[i][j],dp[i-1][k]) ,其中k满足c

usaco 1.3 Prime Cryptarithm(简单哈希表暴搜剪枝)

思路: 1. 用一个 hash[ ] 数组存放输入的数字,令 hash[ tmp ]=1 。 2. 一个自定义函数 check( ) ,检查各位是否为输入的数字。 3. 暴搜。第一行数从 100到999,第二行数从 10到99。 4. 剪枝。 代码: /*ID: who jayLANG: C++TASK: crypt1*/#include<stdio.h>bool h

【WebGPU Unleashed】1.1 绘制三角形

一部2024新的WebGPU教程,作者Shi Yan。内容很好,翻译过来与大家共享,内容上会有改动,加上自己的理解。更多精彩内容尽在 dt.sim3d.cn ,关注公众号【sky的数孪技术】,技术交流、源码下载请添加微信号:digital_twin123 在 3D 渲染领域,三角形是最基本的绘制元素。在这里,我们将学习如何绘制单个三角形。接下来我们将制作一个简单的着色器来定义三角形内的像素

状态dp总结

zoj 3631  N 个数中选若干数和(只能选一次)<=M 的最大值 const int Max_N = 38 ;int a[1<<16] , b[1<<16] , x[Max_N] , e[Max_N] ;void GetNum(int g[] , int n , int s[] , int &m){ int i , j , t ;m = 0 ;for(i = 0 ;