鱼C论坛

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

[已解决]通过穷举找到正确的解答方案!

[复制链接]
发表于 2019-10-25 23:21:00 | 显示全部楼层 |阅读模式

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

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

x
目的:想通过程序解决如下问题!将全部灯泡点亮。
0     1                                       
1     0               
1     1                                          
0     1                                       
代表8个灯泡,(1---亮,0---灭)如何将他们全部点亮。
规则:点击一个灯泡,他所在列的灯泡全部取反,另一列与之同行的灯泡状态也取反;(点一下,有5个灯泡改变状态);
各位大佬们有没有什么好办法!
最佳答案
2019-10-26 05:21:32
本帖最后由 Croper 于 2019-10-26 05:24 编辑

之前练习时写了个A星算法解决开灯游戏的,改了一下toggle函数应该能符合你的要求
  1. #include <iostream>
  2. #include <vector>
  3. #include <utility>
  4. #include <unordered_map>
  5. #include <set>
  6. #include <string>
  7. using namespace std;

  8. //灯泡类
  9. //储存单个灯泡的状态,使用toggle切换状态

  10. class board;

  11. class blub {
  12. friend class board;
  13. private:
  14.         int _state;     //当前状态,0为关闭,1为开启
  15.         board* _master; //指向处于的墙
  16. public:
  17.         blub(board* master=0) :_state(0),_master(master) {};

  18.         int toggle();    //切换状态,返回切换后的状态

  19.         operator int() const {
  20.                 return _state;
  21.         }
  22. };

  23. //墙类
  24. //墙上有X*Y个灯泡
  25. class board {
  26. friend class blub;
  27. friend class board_hash;
  28. friend class board_equal;
  29. friend class board_cmp;
  30. private:
  31.         vector<vector<blub>> _grid;  //存储墙上所有灯泡
  32.         int _clightblub;             //记录发亮的灯泡数目
  33. public:

  34.         board(vector<vector<int>> base) {
  35.                 _clightblub = 0;
  36.                 _grid.resize(base.size(), vector<blub>(base[0].size(),blub(this)));
  37.                 for (int i = 0; i < base.size(); ++i) {
  38.                         for (int j = 0; j < base[i].size(); ++j) {
  39.                                 if (base[i][j]) {
  40.                                         _grid[i][j].toggle();
  41.                                 }
  42.                         }
  43.                 }
  44.         }

  45.         board(const board& origin) {
  46.                 _grid = origin._grid;
  47.                 _clightblub = origin._clightblub;
  48.                 for (int i = 0; i < _grid.size(); ++i) {
  49.                         for (int j = 0; j < _grid[i].size(); ++j) {
  50.                                 _grid[i][j]._master = this;
  51.                         }
  52.                 }
  53.         }
  54.         size_t width() const {
  55.                 if (_grid.size() == 0) return 0;
  56.                 return _grid[0].size();
  57.         }

  58.         size_t height() const {
  59.                 return _grid.size();
  60.         }

  61.         /*
  62.         void toggle(int y, int x) {  //切换坐标为(x,y)的灯泡以及相邻灯泡的状态
  63.                 if (y < 0 || y >= _grid.size() || x < 0 || x >= _grid[y].size()) {
  64.                         return;
  65.                 }

  66.                 _grid[y][x].toggle();
  67.                 if (y - 1 >= 0) _grid[y - 1][x].toggle();
  68.                 if (y + 1 < _grid.size()) _grid[y + 1][x].toggle();
  69.                 if (x - 1 >= 0) _grid[y][x - 1].toggle();
  70.                 if (x + 1 < _grid[y].size()) _grid[y][x + 1].toggle();
  71.         }
  72.         */
  73.         void toggle(int y, int x) {  //切换坐标为(x,y)的灯泡以及与其相同行列的灯泡的状态
  74.                 if (y < 0 || y >= _grid.size() || x < 0 || x >= _grid[y].size()) {
  75.                         return;
  76.                 }
  77.                 for (int x1 = 0; x1 < _grid[y].size(); ++x1) {
  78.                         _grid[y][x1].toggle();
  79.                 }
  80.                 for (int y1 = 0; y1 < _grid.size(); ++y1) {
  81.                         _grid[y1][x].toggle();
  82.                 }
  83.                 _grid[y][x].toggle();
  84.         }

  85.         int clightblub() const{  //返回亮的灯泡的数目
  86.                 return _clightblub;
  87.         }

  88.         bool Alllight() const {  //是否所有灯泡都亮了
  89.                 return _clightblub == _grid.size()*_grid[0].size();
  90.         }
  91. };

  92. int blub::toggle() {      //切换状态,返回切换后的状态
  93.         _state = 1 - _state;
  94.         if (_master != 0) {
  95.                 _master->_clightblub += (_state ? 1 : -1);
  96.         }
  97.         return _state;
  98. }
  99. class board_hash {  //网上抄的hashcode计算方法
  100. public:
  101.         size_t operator()(const board& b) const {
  102.                 const vector<vector<blub>>& grid = b._grid;
  103.                 size_t ret = 17;
  104.                 for (int y=0;y<grid.size();++y){
  105.                         for (int x = 0; x < grid[y].size(); ++x) {
  106.                                 ret = ret * 31 + grid[y][x];
  107.                         }
  108.                 }
  109.                 return ret;
  110.         }
  111. };

  112. class board_equal {
  113. public:
  114.         bool operator()(const board& b1, const board& b2) const {
  115.                 bool b= b1._grid == b2._grid;
  116.                 return b1._grid == b2._grid;
  117.         }
  118. };

  119. class board_cmp {
  120. public:
  121.         bool operator()(const board& b1, const board& b2) const {
  122.                 if (b1._grid.size() == 0 && b2._grid.size() == 0) {
  123.                         return false;
  124.                 }
  125.                 const vector<vector<blub>>& grid1 = b1._grid;
  126.                 const vector<vector<blub>>& grid2 = b2._grid;
  127.                 if (grid1.size() != grid2.size()) {
  128.                         return grid1.size() < grid2.size();
  129.                 }
  130.                 if (grid1[0].size() != grid2[0].size()) {
  131.                         return grid1[0].size() < grid2[0].size();
  132.                 }
  133.                 if (b1.clightblub() != b2.clightblub()) {
  134.                         return b1.clightblub() > b2.clightblub();
  135.                 }
  136.                 for (int i = 0; i < grid1.size(); ++i) {
  137.                         for (int j = 0; j < grid1[i].size(); ++j) {
  138.                                 if (grid1[i][j] != grid2[i][j]) {
  139.                                         return grid1[i][j] < grid2[i][j];
  140.                                 }
  141.                         }
  142.                 }
  143.                 return false;
  144.         }
  145. };

  146. vector<pair<int, int>> findway(board q) {
  147.         unordered_map<board, int,board_hash,board_equal> close_map;//当值为1时说明其已不需要关注
  148.         set<board, board_cmp> openlist;
  149.         unordered_map<board, vector<pair<int, int>>, board_hash, board_equal> path;
  150.         int n = 0;
  151.         while (!q.Alllight()) {
  152.                 close_map[q] = 1;
  153.                 for (int i = 0; i < q.height(); ++i) {
  154.                         for (int j = 0; j < q.width(); ++j) {
  155.                                 board b = q;
  156.                                 b.toggle(i, j);
  157.                                 n++;
  158.                                 if (close_map[b] == 0) {
  159.                                         path[b] = path[q];
  160.                                         bool duplicate = false;  
  161.                                         for (int k = 0; k < path[b].size(); ++k) {
  162.                                                 if (path[b][k] == pair<int, int>(i, j)) {
  163.                                                         path[b].erase(path[b].begin() + k);
  164.                                                         duplicate = true;
  165.                                                         break;
  166.                                                 }
  167.                                         }
  168.                                         if (!duplicate) {
  169.                                                 path[b].push_back({ i,j });
  170.                                         }
  171.                                         openlist.insert(b);
  172.                                 }
  173.                         }
  174.                 }
  175.                 if (n>200000 || openlist.empty()) {
  176.                         return { {-1,-1} };
  177.                 }
  178.                 q = std::move(*openlist.begin());
  179.                 openlist.erase(openlist.begin());
  180.         }
  181.         return path[q];
  182. }

  183. int main() {
  184.         board q = vector<vector<int>>({
  185.         {0,1},
  186.         {1,0},
  187.         {1,1},
  188.         {0,0},
  189.         });

  190.         auto a = findway(q);
  191.         for (int i = 0; i < a.size(); ++i) {
  192.                 cout << a[i].first << "," << a[i].second << endl;
  193.         }
  194.         system("pause");
  195. }
复制代码

得到答案
  1. 3,1
  2. 1,0
  3. 0,1
  4. 3,0
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2019-10-26 05:21:32 | 显示全部楼层    本楼为最佳答案   
本帖最后由 Croper 于 2019-10-26 05:24 编辑

之前练习时写了个A星算法解决开灯游戏的,改了一下toggle函数应该能符合你的要求
  1. #include <iostream>
  2. #include <vector>
  3. #include <utility>
  4. #include <unordered_map>
  5. #include <set>
  6. #include <string>
  7. using namespace std;

  8. //灯泡类
  9. //储存单个灯泡的状态,使用toggle切换状态

  10. class board;

  11. class blub {
  12. friend class board;
  13. private:
  14.         int _state;     //当前状态,0为关闭,1为开启
  15.         board* _master; //指向处于的墙
  16. public:
  17.         blub(board* master=0) :_state(0),_master(master) {};

  18.         int toggle();    //切换状态,返回切换后的状态

  19.         operator int() const {
  20.                 return _state;
  21.         }
  22. };

  23. //墙类
  24. //墙上有X*Y个灯泡
  25. class board {
  26. friend class blub;
  27. friend class board_hash;
  28. friend class board_equal;
  29. friend class board_cmp;
  30. private:
  31.         vector<vector<blub>> _grid;  //存储墙上所有灯泡
  32.         int _clightblub;             //记录发亮的灯泡数目
  33. public:

  34.         board(vector<vector<int>> base) {
  35.                 _clightblub = 0;
  36.                 _grid.resize(base.size(), vector<blub>(base[0].size(),blub(this)));
  37.                 for (int i = 0; i < base.size(); ++i) {
  38.                         for (int j = 0; j < base[i].size(); ++j) {
  39.                                 if (base[i][j]) {
  40.                                         _grid[i][j].toggle();
  41.                                 }
  42.                         }
  43.                 }
  44.         }

  45.         board(const board& origin) {
  46.                 _grid = origin._grid;
  47.                 _clightblub = origin._clightblub;
  48.                 for (int i = 0; i < _grid.size(); ++i) {
  49.                         for (int j = 0; j < _grid[i].size(); ++j) {
  50.                                 _grid[i][j]._master = this;
  51.                         }
  52.                 }
  53.         }
  54.         size_t width() const {
  55.                 if (_grid.size() == 0) return 0;
  56.                 return _grid[0].size();
  57.         }

  58.         size_t height() const {
  59.                 return _grid.size();
  60.         }

  61.         /*
  62.         void toggle(int y, int x) {  //切换坐标为(x,y)的灯泡以及相邻灯泡的状态
  63.                 if (y < 0 || y >= _grid.size() || x < 0 || x >= _grid[y].size()) {
  64.                         return;
  65.                 }

  66.                 _grid[y][x].toggle();
  67.                 if (y - 1 >= 0) _grid[y - 1][x].toggle();
  68.                 if (y + 1 < _grid.size()) _grid[y + 1][x].toggle();
  69.                 if (x - 1 >= 0) _grid[y][x - 1].toggle();
  70.                 if (x + 1 < _grid[y].size()) _grid[y][x + 1].toggle();
  71.         }
  72.         */
  73.         void toggle(int y, int x) {  //切换坐标为(x,y)的灯泡以及与其相同行列的灯泡的状态
  74.                 if (y < 0 || y >= _grid.size() || x < 0 || x >= _grid[y].size()) {
  75.                         return;
  76.                 }
  77.                 for (int x1 = 0; x1 < _grid[y].size(); ++x1) {
  78.                         _grid[y][x1].toggle();
  79.                 }
  80.                 for (int y1 = 0; y1 < _grid.size(); ++y1) {
  81.                         _grid[y1][x].toggle();
  82.                 }
  83.                 _grid[y][x].toggle();
  84.         }

  85.         int clightblub() const{  //返回亮的灯泡的数目
  86.                 return _clightblub;
  87.         }

  88.         bool Alllight() const {  //是否所有灯泡都亮了
  89.                 return _clightblub == _grid.size()*_grid[0].size();
  90.         }
  91. };

  92. int blub::toggle() {      //切换状态,返回切换后的状态
  93.         _state = 1 - _state;
  94.         if (_master != 0) {
  95.                 _master->_clightblub += (_state ? 1 : -1);
  96.         }
  97.         return _state;
  98. }
  99. class board_hash {  //网上抄的hashcode计算方法
  100. public:
  101.         size_t operator()(const board& b) const {
  102.                 const vector<vector<blub>>& grid = b._grid;
  103.                 size_t ret = 17;
  104.                 for (int y=0;y<grid.size();++y){
  105.                         for (int x = 0; x < grid[y].size(); ++x) {
  106.                                 ret = ret * 31 + grid[y][x];
  107.                         }
  108.                 }
  109.                 return ret;
  110.         }
  111. };

  112. class board_equal {
  113. public:
  114.         bool operator()(const board& b1, const board& b2) const {
  115.                 bool b= b1._grid == b2._grid;
  116.                 return b1._grid == b2._grid;
  117.         }
  118. };

  119. class board_cmp {
  120. public:
  121.         bool operator()(const board& b1, const board& b2) const {
  122.                 if (b1._grid.size() == 0 && b2._grid.size() == 0) {
  123.                         return false;
  124.                 }
  125.                 const vector<vector<blub>>& grid1 = b1._grid;
  126.                 const vector<vector<blub>>& grid2 = b2._grid;
  127.                 if (grid1.size() != grid2.size()) {
  128.                         return grid1.size() < grid2.size();
  129.                 }
  130.                 if (grid1[0].size() != grid2[0].size()) {
  131.                         return grid1[0].size() < grid2[0].size();
  132.                 }
  133.                 if (b1.clightblub() != b2.clightblub()) {
  134.                         return b1.clightblub() > b2.clightblub();
  135.                 }
  136.                 for (int i = 0; i < grid1.size(); ++i) {
  137.                         for (int j = 0; j < grid1[i].size(); ++j) {
  138.                                 if (grid1[i][j] != grid2[i][j]) {
  139.                                         return grid1[i][j] < grid2[i][j];
  140.                                 }
  141.                         }
  142.                 }
  143.                 return false;
  144.         }
  145. };

  146. vector<pair<int, int>> findway(board q) {
  147.         unordered_map<board, int,board_hash,board_equal> close_map;//当值为1时说明其已不需要关注
  148.         set<board, board_cmp> openlist;
  149.         unordered_map<board, vector<pair<int, int>>, board_hash, board_equal> path;
  150.         int n = 0;
  151.         while (!q.Alllight()) {
  152.                 close_map[q] = 1;
  153.                 for (int i = 0; i < q.height(); ++i) {
  154.                         for (int j = 0; j < q.width(); ++j) {
  155.                                 board b = q;
  156.                                 b.toggle(i, j);
  157.                                 n++;
  158.                                 if (close_map[b] == 0) {
  159.                                         path[b] = path[q];
  160.                                         bool duplicate = false;  
  161.                                         for (int k = 0; k < path[b].size(); ++k) {
  162.                                                 if (path[b][k] == pair<int, int>(i, j)) {
  163.                                                         path[b].erase(path[b].begin() + k);
  164.                                                         duplicate = true;
  165.                                                         break;
  166.                                                 }
  167.                                         }
  168.                                         if (!duplicate) {
  169.                                                 path[b].push_back({ i,j });
  170.                                         }
  171.                                         openlist.insert(b);
  172.                                 }
  173.                         }
  174.                 }
  175.                 if (n>200000 || openlist.empty()) {
  176.                         return { {-1,-1} };
  177.                 }
  178.                 q = std::move(*openlist.begin());
  179.                 openlist.erase(openlist.begin());
  180.         }
  181.         return path[q];
  182. }

  183. int main() {
  184.         board q = vector<vector<int>>({
  185.         {0,1},
  186.         {1,0},
  187.         {1,1},
  188.         {0,0},
  189.         });

  190.         auto a = findway(q);
  191.         for (int i = 0; i < a.size(); ++i) {
  192.                 cout << a[i].first << "," << a[i].second << endl;
  193.         }
  194.         system("pause");
  195. }
复制代码

得到答案
  1. 3,1
  2. 1,0
  3. 0,1
  4. 3,0
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-10-26 18:25:40 | 显示全部楼层
Croper 发表于 2019-10-26 05:21
之前练习时写了个A星算法解决开灯游戏的,改了一下toggle函数应该能符合你的要求
得到答案

大佬辛苦了!
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-7-4 12:05

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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