鱼C论坛

 找回密码
 立即注册
查看: 2762|回复: 1

题目166:十字形

[复制链接]
发表于 2016-9-15 00:18:53 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
Criss Cross

A 4x4 grid is filled with digits d, 0 ≤ d ≤ 9.

It can be seen that in the grid

6 3 3 0
5 0 4 3
0 7 1 4
1 2 4 5


the sum of each row and each column has the value 12. Moreover the sum of each diagonal is also 12.

In how many ways can you fill a 4x4 grid with the digits d, 0 ≤ d ≤ 9 so that each row, each column, and both diagonals have the same sum?


题目:

一个 4×4 的网格用数字 d 填充,0 ≤ d ≤ 9。

可以看出,在下面这个网格中:

6 3 3 0
5 0 4 3
0 7 1 4
1 2 4 5

每一行和每一列的和都是 12,此外对角线之和也是 12。


那么,你能以多少种方法用 0-9 的数字填充一个 4×4 的网格,使得每行、每列和对角线的和相等呢?

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-10-5 10:33:40 | 显示全部楼层
应用穷举搜索。
答案:7130034
  1. #include <iostream>
  2. #include <vector>
  3. #include <set>
  4. #include <algorithm>
  5. #include <cstring>
  6. #include <omp.h>
  7. using namespace std;

  8. struct stMatrix//4x4矩阵
  9. {
  10.   unsigned char a[4][4];
  11.   stMatrix(void)
  12.   {
  13.     memset(a, 0, sizeof(a));
  14.   }
  15.   bool check(int d)//验证对角线与反对角线元素之和是否满足要求
  16.   {
  17.     if (int(a[0][0] + a[1][1] + a[2][2] + a[3][3]) != d)
  18.       return false;
  19.     if (int(a[3][0] + a[2][1] + a[1][2] + a[0][3]) != d)
  20.       return false;
  21.     return true;
  22.   }
  23. };

  24. inline void getrow(int d, int n, vector<short>& vRows) //生成所有满足条件的行
  25. {
  26.   int s = 0, k = n;
  27.   while (k > 0)
  28.   {
  29.     s += k % 10;
  30.     k /= 10;
  31.   }
  32.   if (s == d)
  33.     vRows.push_back(n);
  34. }

  35. long long cml(stMatrix m)//将矩阵变成long long以便查重
  36. {
  37.   long long x = 0;
  38.   for (int r = 3; r >= 0; --r)
  39.   {
  40.     for (int c = 3; c >= 0; --c)
  41.       x = x * 10 + m.a[r][c];
  42.   }
  43.   return x;
  44. }

  45. void gm1(stMatrix m, int d, set<long long>& sM)//检验矩阵是否满足要求并查重
  46. {
  47.   if (m.check(d))
  48.   {
  49.     sM.insert(cml(m));
  50.     stMatrix m1;
  51.     for (int i = 0; i < 4; ++i)
  52.     {
  53.       for (int j = 0; j < 4; ++j)
  54.         m1.a[i][j] = m.a[j][i];
  55.     }
  56.     sM.insert(cml(m1));
  57.     for (int i = 0; i < 4; ++i)
  58.     {
  59.       for (int j = 0; j < 4; ++j)
  60.         m1.a[i][j] = m.a[3 - i][3 - j];
  61.     }
  62.     sM.insert(cml(m1));
  63.     for (int i = 0; i < 4; ++i)
  64.     {
  65.       for (int j = 0; j < 4; ++j)
  66.         m1.a[i][j] = m.a[3 - j][3 - i];
  67.     }
  68.     sM.insert(cml(m1));
  69.   }
  70. }

  71. void gm(const short b[3], int d, set<long long>& sM)//根据前3行来生成一个矩阵
  72. {
  73.   stMatrix m;
  74.   short c[3];
  75.   c[0] = b[0];
  76.   c[1] = b[1];
  77.   c[2] = b[2];
  78.   short s = 0;
  79.   for (int i = 0; i < 4; ++i)//生成矩阵
  80.   {
  81.     m.a[0][i] = c[0] % 10;
  82.     m.a[1][i] = c[1] % 10;
  83.     m.a[2][i] = c[2] % 10;
  84.     m.a[3][i] = d - (m.a[0][i] + m.a[1][i] + m.a[2][i]);
  85.     if (m.a[3][i] < 0 || m.a[3][i]>9)
  86.       return;
  87.     s += m.a[3][i];
  88.     c[0] /= 10;
  89.     c[1] /= 10;
  90.     c[2] /= 10;
  91.   }
  92.   if (s != d)
  93.     return;
  94.   int x[4] = { 0,1,2,3 };
  95.   do //对行进行排列变换
  96.   {
  97.     stMatrix m1;
  98.     for (int i = 0; i < 4; ++i)
  99.     {
  100.       for (int j = 0; j < 4; ++j)
  101.         m1.a[i][j] = m.a[x[i]][j];
  102.     }
  103.     int y[4] = { 0,1,2,3 };
  104.     do //对列进行排列变换
  105.     {
  106.       stMatrix m2;
  107.       for (int i = 0; i < 4; ++i)
  108.       {
  109.         for (int j = 0; j < 4; ++j)
  110.           m2.a[i][j] = m1.a[i][y[j]];
  111.       }
  112.       gm1(m2, d, sM);//检验并查重
  113.     } while (next_permutation(y, y + 4));
  114.   } while (next_permutation(x, x + 4));
  115. }

  116. int main(void)
  117. {
  118.   long long nCount = 0;
  119. #pragma omp parallel for reduction(+:nCount) schedule(dynamic,1)
  120.   for (int d = 0; d <= 18; ++d)//对和值进行枚举
  121.   {
  122.     vector<short> vRows;
  123.     for (short i = 0; i < 10000; ++i)
  124.       getrow(d, i, vRows);
  125.     set<long long> sM;
  126.     for (int i = 0; i < (int)vRows.size(); ++i)
  127.     {
  128.       short b[3];
  129.       b[0] = vRows[i];
  130.       for (int j = i; j < (int)vRows.size(); ++j)
  131.       {
  132.         b[1] = vRows[j];
  133.         for (int k = j; k < (int)vRows.size(); ++k)
  134.         {
  135.           b[2] = vRows[k];
  136.           gm(b, d, sM);
  137.         }
  138.       }
  139.     }
  140.     nCount += sM.size();
  141.     if (36 - d != d)
  142.       nCount += sM.size();//根据对称性
  143.   }
  144.   cout << nCount << endl;
  145.   return 0;
  146. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-20 01:50

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表