鱼C论坛

 找回密码
 立即注册
查看: 2750|回复: 2

[已解决]神奇的幻方

[复制链接]
发表于 2021-5-1 19:51:42 From FishC Mobile | 显示全部楼层 |阅读模式

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

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

x
7岁的小明在科普杂志上看到了关于奇数阶幻方的解法,方法是首先数字 1 放在首行最中间的格子中,然后向右上角斜行,并依次把后续数字填入对应位置。注意特殊情况:
1)如果超出了上边界,就以出框后的虚拟方格位置为基准,将数字(记为 k )平移至最下行对应的格子中;
2)如果超出了右边界,就以出框后的虚拟方格位置为基准,将 k 平移至最左列对应的格子中;
3)如果右上角格子已被其它数字占领,就将 k填写在数字 k1 所在位置的下方格子中。以此法得出幻方。例如五阶幻方,按此法生成的结果(请忽略表格的第一行),可以注意到,每一行每一列的和,两个对角线的和均为65:
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
现在小明手里有一个幻方,但是不小心把M个格子给污染了。他会告诉你这M个格子的位置,并且想让你告诉他询问的位置对应的数是多少。
输入数据
第一行两个数 N,M(N≤10000,保证N为奇数,M≤100000)
N,M(N≤10000,保证N为奇数,M≤100000)
,表示幻方的阶数和被污染的格子数
接下来 M 行,每行两个数 x,y(1≤x,y≤n) ,表示污染的格子在第x 行,第y列。
输出数据
共M行,每行一个数,为所求位置的数字。
样例输入
5 2
1 3
5 3
样例输出
1
25
求大佬答疑解惑,小白真的不会写
最佳答案
2021-5-6 12:04:38
  1. #include<iostream>
  2. #include <fstream>
  3. #include<string>
  4. #include <vector>

  5. using namespace std;

  6. class MagicSquare
  7. {
  8. public:
  9.     MagicSquare() = delete;
  10.     MagicSquare(MagicSquare&) = delete;
  11.     MagicSquare(MagicSquare&&) = delete;
  12.     MagicSquare(int len) : len(len)
  13.     {
  14.         CreateSquare();
  15.     }

  16.     void PrintSquare()
  17.     {
  18.         for (int i = 0; i < len; ++i)
  19.         {
  20.             for (int j = 0; j < len; j++)
  21.             {
  22.                 printf_s("%3d ", square[i * len + j]);
  23.             }
  24.             printf_s("\n");
  25.         }
  26.     }

  27. private:
  28.     void CreateSquare()
  29.     {
  30.         square = new int[len * len * sizeof(int)];
  31.         memset(square, 0, len * len * sizeof(int));

  32.         judgeArr = new int[len * len * sizeof(int)];
  33.         memset(judgeArr, 0, len * len * sizeof(int));

  34.         //w 列  h 行
  35.         int w = len / 2, h = 0;
  36.         //已经填充的数量
  37.         int total = 0;
  38.         //填充数字
  39.         int num = 1;

  40.         while (total < len * len)
  41.         {
  42.             square[h * len + w] = num;
  43.             judgeArr[h * len + w] = 1;
  44.             int prevW = w;
  45.             int prevH = h;

  46.             h--;
  47.             w++;
  48.             total++;
  49.             num++;

  50.             //下个位置已经填过值 或 超出范围
  51.             while (w >= len || h < 0 || judgeArr[h * len + w] == 1)
  52.             {
  53.                 int time = 0;
  54.                 if (w >= len)
  55.                     w = 0;
  56.                 if (h < 0)
  57.                     h = len - 1;

  58.                 if (judgeArr[h * len + w] == 1)
  59.                 {
  60.                     //回溯
  61.                     w = prevW;
  62.                     h = prevH;
  63.                     
  64.                     if (time == 0)
  65.                         h++;
  66.                     else
  67.                     {
  68.                         h--, w++;
  69.                     }
  70.                     prevW = w;
  71.                     prevH = h;
  72.                     time++;
  73.                 }
  74.             }
  75.         }
  76.     }

  77.     //幻方边长
  78.     int len;
  79.     //幻方
  80.     int* square;
  81.     //判断当前位置是否已经存在值的数组
  82.     int* judgeArr;
  83. };

  84. int main()
  85. {
  86.     MagicSquare ms(5);
  87.     ms.PrintSquare();

  88.     return 0;
  89. }
复制代码


我只写了创建幻方,剩下的就是输入位置,然后输出数组那个位置的值,没啥玩意  自己写吧
QQ截图20210506120417.png
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-5-6 12:04:38 | 显示全部楼层    本楼为最佳答案   
  1. #include<iostream>
  2. #include <fstream>
  3. #include<string>
  4. #include <vector>

  5. using namespace std;

  6. class MagicSquare
  7. {
  8. public:
  9.     MagicSquare() = delete;
  10.     MagicSquare(MagicSquare&) = delete;
  11.     MagicSquare(MagicSquare&&) = delete;
  12.     MagicSquare(int len) : len(len)
  13.     {
  14.         CreateSquare();
  15.     }

  16.     void PrintSquare()
  17.     {
  18.         for (int i = 0; i < len; ++i)
  19.         {
  20.             for (int j = 0; j < len; j++)
  21.             {
  22.                 printf_s("%3d ", square[i * len + j]);
  23.             }
  24.             printf_s("\n");
  25.         }
  26.     }

  27. private:
  28.     void CreateSquare()
  29.     {
  30.         square = new int[len * len * sizeof(int)];
  31.         memset(square, 0, len * len * sizeof(int));

  32.         judgeArr = new int[len * len * sizeof(int)];
  33.         memset(judgeArr, 0, len * len * sizeof(int));

  34.         //w 列  h 行
  35.         int w = len / 2, h = 0;
  36.         //已经填充的数量
  37.         int total = 0;
  38.         //填充数字
  39.         int num = 1;

  40.         while (total < len * len)
  41.         {
  42.             square[h * len + w] = num;
  43.             judgeArr[h * len + w] = 1;
  44.             int prevW = w;
  45.             int prevH = h;

  46.             h--;
  47.             w++;
  48.             total++;
  49.             num++;

  50.             //下个位置已经填过值 或 超出范围
  51.             while (w >= len || h < 0 || judgeArr[h * len + w] == 1)
  52.             {
  53.                 int time = 0;
  54.                 if (w >= len)
  55.                     w = 0;
  56.                 if (h < 0)
  57.                     h = len - 1;

  58.                 if (judgeArr[h * len + w] == 1)
  59.                 {
  60.                     //回溯
  61.                     w = prevW;
  62.                     h = prevH;
  63.                     
  64.                     if (time == 0)
  65.                         h++;
  66.                     else
  67.                     {
  68.                         h--, w++;
  69.                     }
  70.                     prevW = w;
  71.                     prevH = h;
  72.                     time++;
  73.                 }
  74.             }
  75.         }
  76.     }

  77.     //幻方边长
  78.     int len;
  79.     //幻方
  80.     int* square;
  81.     //判断当前位置是否已经存在值的数组
  82.     int* judgeArr;
  83. };

  84. int main()
  85. {
  86.     MagicSquare ms(5);
  87.     ms.PrintSquare();

  88.     return 0;
  89. }
复制代码


我只写了创建幻方,剩下的就是输入位置,然后输出数组那个位置的值,没啥玩意  自己写吧
QQ截图20210506120417.png
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-5-7 13:01:47 | 显示全部楼层
本帖最后由 yuxijian2020 于 2021-5-7 15:18 编辑
  1. #include <iostream>
  2. #include <vector>

  3. using namespace std;

  4. struct Point
  5. {
  6.     int x;
  7.     int y;
  8.     Point() : x(0), y(0) {}
  9.     Point(int x, int y) : x(x), y(y) {}
  10. };

  11. class MagicSquare
  12. {
  13. public:
  14.     MagicSquare() = delete;
  15.     MagicSquare(MagicSquare&) = delete;
  16.     MagicSquare(MagicSquare&&) = delete;
  17.     explicit MagicSquare(int len) : len(len)
  18.     {
  19.         CreateSquare();
  20.     }

  21.     ~MagicSquare()
  22.     {
  23.         if (judgeArr)
  24.             delete[] judgeArr;
  25.         if (square)
  26.             delete[] square;
  27.         len = 0;
  28.     }

  29.     void PrintSquare()
  30.     {
  31.         for (int i = 0; i < len; ++i)
  32.         {
  33.             for (int j = 0; j < len; j++)
  34.             {
  35.                 printf_s("%3d ", square[i * len + j]);
  36.             }
  37.             printf_s("\n");
  38.         }
  39.     }

  40.     int GetNumberByPoint(Point p) { return square[p.x * len + p.y]; }

  41. private:
  42.     void CreateSquare()
  43.     {
  44.         square = new int[len * len * sizeof(int)];
  45.         memset(square, 0, len * len * sizeof(int));

  46.         judgeArr = new int[len * len * sizeof(int)];
  47.         memset(judgeArr, 0, len * len * sizeof(int));

  48.         //w 列  h 行
  49.         int w = len / 2, h = 0;
  50.         //已经填充的数量
  51.         int total = 0;
  52.         //填充数字
  53.         int num = 1;

  54.         while (total < len * len)
  55.         {
  56.             square[h * len + w] = num;
  57.             judgeArr[h * len + w] = 1;
  58.             int prevW = w;
  59.             int prevH = h;

  60.             h--;
  61.             w++;
  62.             total++;
  63.             num++;

  64.             //下个位置已经填过值 或 超出范围
  65.             while (w >= len || h < 0 || judgeArr[h * len + w] == 1)
  66.             {
  67.                 int time = 0;
  68.                 if (w >= len)
  69.                     w = 0;
  70.                 if (h < 0)
  71.                     h = len - 1;

  72.                 if (judgeArr[h * len + w] == 1)
  73.                 {
  74.                     //回溯
  75.                     w = prevW;
  76.                     h = prevH;
  77.                     
  78.                     if (time == 0)
  79.                         h++;
  80.                     else
  81.                     {
  82.                         h--, w++;
  83.                     }
  84.                     prevW = w;
  85.                     prevH = h;
  86.                     time++;
  87.                 }
  88.             }
  89.         }
  90.     }

  91.     //幻方边长
  92.     int len;
  93.     //幻方
  94.     int* square;
  95.     //判断当前位置是否已经存在值的数组
  96.     int* judgeArr;
  97. };

  98. vector<int> GetInputAndResult()
  99. {
  100.     int len = 0, sum = 0;
  101.    
  102.     while (len % 2 == 0 || sum > len * len)
  103.     {
  104.         printf_s("请输入幻方阶数(奇数)和被污染的格子数:");
  105.         scanf_s("%d%*c%d%*c", &len, &sum);
  106.         
  107.         if (len % 2 == 0)
  108.         {
  109.             printf_s("幻方的阶数必须为奇数!\n");
  110.             continue;
  111.         }

  112.         if (sum > len * len)
  113.         {
  114.             printf_s("被污染的格子数超过了总格子数!\n");
  115.             continue;
  116.         }
  117.     }

  118.     MagicSquare ms(len);
  119.     Point p;
  120.     vector<int> result;

  121.     for (int i = 0; i < sum; ++i)
  122.     {
  123.         printf("请输入第 %d 个被污染的格子坐标:", i + 1);
  124.         scanf_s("%d%*c%d%*c", &p.x, &p.y);
  125.         //坐标超出范围
  126.         if ((p.x < 1 || p.x > len) && (p.y < 1 || p.y > len))
  127.         {
  128.             i--;
  129.             continue;
  130.         }

  131.         p.x--, p.y--;
  132.         result.push_back(ms.GetNumberByPoint(p));
  133.     }

  134.     return result;
  135. }

  136. int main()
  137. {
  138.     vector<int> result(GetInputAndResult());

  139.     for (const auto& i : result) { printf_s("%d\n", i); }

  140.     return 0;
  141. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-7-7 01:23

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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