华为OD机试-九宫格

题目描述

九宫格是一款广为流传的游戏,起源于河图洛书。

游戏规则是:1到9九个数字放在3×3的格子中,要求每行、每列以及两个对角线上的三数之和都等于15.

在金麻名著《射雕英雄传》中黃蓉曾给九宫格的一种解法,口诀:戴九恩一,左三右七,二四有肩,八六为足,五居中央。解法如图所示。

现在有一种新的玩法,给九个不同的数字,将这九个数字放在3×3的格子中,要求每行、每列以及两个对角线上的三数之积相等(三阶积幻方)。其中一个三阶幻方如图:

解释:每行、每列以及两个对角线上的三数之积相等,都为216。请设计一种算法,将给定的九个数宇重新排列后,使其满足三阶积幻方的要求。

排列后的九个数宇中:第1-3个数字为方格的第一行,第4-6个数宇为方格的第二行,第7-9个数字为方格的第三行。

输入描述

九个不同的数宇,每个数字之间用空格分开。

0<数字<10^7。0<排列后满足要求的每行、每列以及两个对角线上的三数之积 < 2^31-1。

输出描述

九个数字所有满足要求的排列,每个数字之间用空格分开。每行输出一个满足要求的排列。

要求输出的排列升序排序,即:对于排列A (A1.A2.A3…A9)和排列B(B1,B2,B3…B9),从排列的第1个数字开始,遇到Ai<Bi,则排列A<排列B (1<=j<=9)。

说明:用例保证至少有一种排列组合满足条件。

用例

输入

75 36 10 4 30 225 90 25 12

输出

10 36 75 225 30 4 12 25 90

10 225 12 36 30 25 75 4 90

12 25 90 225 30 4 10 36 75

12 225 10 25 30 36 90 4 75

75 4 90 36 30 25 10 225 12

75 36 10 4 30 225 90 25 12

90 4 75 25 30 36 12 225 10

90 25 12 4 30 225 75 36 10

题目解析

简单的全排列问题。

关于全排列的入门,可以看

组合与排列的区别,回溯算法求解的时候,有何不同?| LeetCode:46.全排列_哔哩哔哩_bilibili

练习题可以做leetcode上:LeetCode - 46 全排列

基于回溯算法的全排列求解是一种暴力解法,即枚举出全部排列情况,因此对大数量级而言,我们应该慎用,但是本题,已经明确指出了求解9个数字的全排列,因此排列情况共有9!个,即362880个,数量级还好,因此可以使用暴力求解。

另外,求出符合要求的排列,还需要对各排列进行排序,排序是按各个数字大小来比较的,大家可以看下代码中关于排序的实现。

JavaScript算法源码

/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline");
 
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});
 
rl.on("line", (line) => {
  const arr = line.split(" ").map(Number);
  getResult(arr);
});
 
function getResult(arr) {
  const res = [];
  dfs(arr, [], [], res);
 
  res.sort((a, b) => {
    for (let i = 0; i < 9; i++) {
      if (a[i] !== b[i]) return a[i] - b[i];
    }
    return 0;
  });
 
  res.forEach((a) => console.log(a.join(" ")));
}
 
function dfs(arr, used, path, res) {
  if (path.length === arr.length) {
    if (check(path)) {
      res.push([...path]);
    }
    return;
  }
 
  for (let i = 0; i < arr.length; i++) {
    if (!used[i]) {
      path.push(arr[i]);
      used[i] = true;
      dfs(arr, used, path, res);
      used[i] = false;
      path.pop();
    }
  }
}
 
function check(a) {
  /**
   * a0 a1 a2
   * a3 a4 a5
   * a6 a7 a8
   */
 
  const r1 = a[0] * a[1] * a[2];
 
  const r2 = a[3] * a[4] * a[5];
  if (r1 != r2) return false;
 
  const r3 = a[6] * a[7] * a[8];
  if (r1 != r3) return false;
 
  const c1 = a[0] * a[3] * a[6];
  if (r1 != c1) return false;
 
  const c2 = a[1] * a[4] * a[7];
  if (r1 != c2) return false;
 
  const c3 = a[2] * a[5] * a[8];
  if (r1 != c3) return false;
 
  const s1 = a[0] * a[4] * a[8];
  if (r1 != s1) return false;
 
  const s2 = a[2] * a[4] * a[6];
  if (r1 != s2) return false;
 
  return true;
}

Java算法源码

import java.util.*;
 
public class Main {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
 
    Integer[] arr =
        Arrays.stream(sc.nextLine().split(" ")).map(Integer::parseInt).toArray(Integer[]::new);
    getResult(arr);
  }
 
  public static void getResult(Integer[] arr) {
    boolean[] used = new boolean[arr.length];
    LinkedList<Integer> path = new LinkedList<>();
    ArrayList<Integer[]> res = new ArrayList<>();
 
    dfs(arr, used, path, res);
 
    res.sort(
        (a, b) -> {
          for (int i = 0; i < 9; i++) {
            if (!Objects.equals(a[i], b[i])) return a[i] - b[i];
          }
          return 0;
        });
 
    for (Integer[] re : res) {
      StringJoiner sj = new StringJoiner(" ");
      for (Integer i : re) {
        sj.add(i + "");
      }
      System.out.println(sj);
    }
  }
 
  public static void dfs(
      Integer[] arr, boolean[] used, LinkedList<Integer> path, ArrayList<Integer[]> res) {
    if (path.size() == arr.length) {
      if (check(path)) {
        Integer[] a = path.toArray(new Integer[0]);
        res.add(a);
      }
      return;
    }
 
    for (int i = 0; i < arr.length; i++) {
      if (!used[i]) {
        path.add(arr[i]);
        used[i] = true;
        dfs(arr, used, path, res);
        used[i] = false;
        path.removeLast();
      }
    }
  }
 
  public static boolean check(LinkedList<Integer> path) {
    Integer[] a = path.toArray(new Integer[0]);
 
    int r1 = a[0] * a[1] * a[2];
 
    int r2 = a[3] * a[4] * a[5];
    if (r1 != r2) return false;
 
    int r3 = a[6] * a[7] * a[8];
    if (r1 != r3) return false;
 
    int c1 = a[0] * a[3] * a[6];
    if (r1 != c1) return false;
 
    int c2 = a[1] * a[4] * a[7];
    if (r1 != c2) return false;
 
    int c3 = a[2] * a[5] * a[8];
    if (r1 != c3) return false;
 
    int s1 = a[0] * a[4] * a[8];
    if (r1 != s1) return false;
 
    int s2 = a[2] * a[4] * a[6];
    if (r1 != s2) return false;
 
    return true;
  }
}

Python算法源码

# 输入获取
arr = list(map(int, input().split()))
 
 
# 算法入口
def getResult(arr):
    res = []
    dfs(arr, [False for i in range(len(arr))], [], res)
 
    res.sort(key=lambda x: (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8]))
 
    for a in res:
        print(" ".join(map(str, a)))
 
 
# 全排列求解
def dfs(arr, used, path, res):
    if len(path) == len(arr):
        if check(path):
            res.append(path[:])
        return
 
    for i in range(len(arr)):
        if not used[i]:
            path.append(arr[i])
            used[i] = True
            dfs(arr, used, path, res)
            used[i] = False
            path.pop()
 
 
# 检查排列a是否符合 每行、每列、两个对角线的乘积相同
def check(a):
    r1 = a[0] * a[1] * a[2]
 
    r2 = a[3] * a[4] * a[5]
    if r1 != r2:
        return False
 
    r3 = a[6] * a[7] * a[8]
    if r1 != r3:
        return False
 
    c1 = a[0] * a[3] * a[6]
    if r1 != c1:
        return False
 
    c2 = a[1] * a[4] * a[7]
    if r1 != c2:
        return False
 
    c3 = a[2] * a[5] * a[8]
    if r1 != c3:
        return False
 
    s1 = a[0] * a[4] * a[8]
    if r1 != s1:
        return False
 
    s2 = a[2] * a[4] * a[6]
    if r1 != s2:
        return False
 
    return True
 
# 调用算法
getResult(arr)

华为OD刷题 文章被收录于专栏

华为OD刷题

全部评论

相关推荐

#牛客帮帮团来啦!有问必答# 非吹牛逼非炫富,真实向各位大佬求助帖。本人简历上的的公司法人是自己,产品是自己独立开发的,但是担心创业经历会让HR抵触,所以将创业经历优化成实习经历,收入也写少了2/3(隐私信息打码)。进大厂是我中学至今的目标。苦于学历不行,所以决定专注提升履历,大一前便注册了一个高中教育公众号,一年涨了3万粉,月入过万,大学一直是经济独立。大二时攒下来10万,我开始创业做产品,是互联网教育/电商/新媒体等领域,大学三年赚了两百多万,前期是产品空白需求大,现在市场饱和,销量见顶,ROI低到经营困难,数据无法大幅度增长,履历的提升已经出现停滞,无法做出更大的业绩来够到进大厂的门槛。我一开始以为创业是加分项,负债的风险和创业的压力(疫情断货、恶意扣分罚款、背刺、竞对攻击等很多生死存亡的节点都让人焦虑痛苦和失眠)是我不想经历第二次的,因为没有合伙人,只能白天上课,晚上熬夜工作,每天睡5,6小时。没想到创业的经历,会有很多HR怀疑我的求职动机,给我带来很多阻挠。不求工资多少,城市哪里,在职场里发展3-5年以上是我坚定不移的人生规划,只为提高自己未来的下限。所以来到牛客向各位大佬求助。看看简历有什么要优化的,怎么写才有机会进大厂,感激不尽! #投递实习岗位前的准备# #找实习多的是你不知道的事# #实习,投递多份简历没人回复怎么办# #没有实习经历,还有机会进大厂吗#
ITTM:首先给大佬敬礼,然后建议是把工作经历和项目经历挪到最上面,这两个是面试时面试官的谈资,然后教育背景要放在最上面,自我评价一般是放最后的。另外,项目经历按照时间倒序排列,最近做的放在前面
点赞 评论 收藏
分享
牛牛不会牛泪:可以先别急着租房,去青旅,或者订个近点的宾馆待几天。先看看要做的能不能学到东西,然后看文档完不完善,写的好不好,mentor对你咋样,公司氛围啥的。情况不对赶快跑路找下家
点赞 评论 收藏
分享
15 14 评论
分享
牛客网
牛客企业服务