同一个世界OL 计算机求解

举报
用户已注销 发表于 2021/11/19 04:14:47 2021/11/19
1.6k+ 0 0
【摘要】 同一个世界 同一个世界OL 同一个世界OL引入了世界关卡,也就是玩家自主设计关卡,其他的玩家来破解。 不像同一个世界,游戏关卡都很对称,比较简单,世界关卡里面有一些很难的关卡。 我写了个程序来破解关卡,不过水平有限,6行5列的关卡大概会需要10秒钟,再大一点的关卡就基本上算不出来了。 思路: 从一个起点出发,使用深度优先搜索...

同一个世界

同一个世界OL

同一个世界OL引入了世界关卡,也就是玩家自主设计关卡,其他的玩家来破解。

不像同一个世界,游戏关卡都很对称,比较简单,世界关卡里面有一些很难的关卡。

我写了个程序来破解关卡,不过水平有限,6行5列的关卡大概会需要10秒钟,再大一点的关卡就基本上算不出来了。

思路:

从一个起点出发,使用深度优先搜索,列出所有可能的路径,利用状态压缩把一条路径映射到1个64位的整数。

另外一个起点也是同样处理,这样就得到2个差不多大小的集合S1、S2

然后遍历S1中的元素,和需要得到的最终结果进行1次位运算直接得到需要的另一条路径,然后查找S2是否包含此路径

代码:


      #include<iostream>
      #include<set>
      using namespace std;
      #define ll long long
      const ll r = 6, c = 5;   //需要手动修改
      int x1 = 0, yy1 = 2, x2 = 5, y2 = 1, result = 20882777;  //需要手动修改
      int has[r][c] =   //需要手动修改
      {
     	1, 1, 1, 1, 1,
     	1, 0, 1, 1, 1,
     	1, 1, 1, 1, 1,
     	1, 1, 1, 1, 1,
     	1, 1, 1, 1, 1,
     	1, 1, 1, 1, 1
      };
      int num[r][c];
      set<pair<ll, pair<int, int>>>se;
      set<ll>se1, se2;
      bool ok(int x, int y)
      {
     	if (x < 0 || x >= r)return false;
     	if (y < 0 || y >= c)return false;
     	if (num[x][y])return false;
     	return has[x][y];
      }
      void dfs(int x, int y)
      {
      	num[x][y] = 1;
      	ll res = 0;
     	for (int i = 0; i < r; i++)for (int j = 0; j < c; j++)res = res * 2 + num[i][j];
     	int si = se.size();
      	se.insert(make_pair(res, make_pair(x, y)));
     	if (si < se.size())
      	{
     		if (ok(x + 1, y))dfs(x + 1, y);
     		if (ok(x - 1, y))dfs(x - 1, y);
     		if (ok(x, y + 1))dfs(x, y + 1);
     		if (ok(x, y - 1))dfs(x, y - 1);
      	}
      	num[x][y] = 0;
      }
      void out(ll n)
      {
      	ll k = 1 << (r*c);
     	for (int i = 0; i < r; i++)
      	{
     		for (int j = 0; j < c; j++)
      		{
      			k /= 2;
     			if (n&k)cout << "●";
     			else cout << "○";
      		}
      		cout << endl;
      	}
      	cout << endl;
      }
      int main()
      {
      	se.clear();
      	se1.clear();
      	se2.clear();
     	for (int ii = 0; ii < r; ii++)for (int jj = 0; jj < c; jj++)num[ii][jj] = 0;
     	dfs(x1, yy1);
      	set<pair<ll, pair<int, int>>>::iterator it;
     	for (it = se.begin(); it != se.end(); it++)se1.insert(it->first);
      	se.clear();
     	for (int ii = 0; ii < r; ii++)for (int jj = 0; jj < c; jj++)num[ii][jj] = 0;
     	dfs(x2, y2);
     	for (it = se.begin(); it != se.end(); it++)se2.insert(it->first);
      	set<ll>::iterator it1;
     	for (it1 = se1.begin(); it1 != se1.end(); it1++)
     	if (se2.find((*it1) ^ result) != se2.end())
      	{
     		out(*it1);
     		out((*it1) ^ result);
     		return 0;
      	}
      	ll temp = 1;
     	for (int i = r - 1; i >= 0; i--)for (int j = c - 1; j >= 0; j--)
      		result -= has[i][j] * temp, temp *= 2;
      	result *= -1;
     	for (it1 = se1.begin(); it1 != se1.end(); it1++)
     	if (se2.find((*it1) ^ result) != se2.end())
      	{
     		out(*it1);
     		out((*it1) ^ result);
      	}
     	return 0;
      }
  
 

使用说明:

代码中有3行标注了 //需要手动修改 ,一共7个整数和1个数组,运行之前根据关卡的实际情况进行修改即可

然后运行即可得到答案。

示例:

一共6行5列,俩起点的坐标分别是(0,2)(5,1),

接下来把颜色信息表示出来,黄色和白色随便哪个对应1,另外一个对应0,空的地方一定是对应0

也就是上图可表示为111110010000010101101010100110或者000001001111101010010101011001

然后把上述两个二进制整数转换成十进制,可以利用http://tool.oschina.net/hexconvert

至此,一共得到7个整数,分别是6,5,0,25,1,1044470438或20882777,依次写到代码里面

最后还有一个has数组,就是用1表示有点(不管颜色),0表示空的地方

如此就完成了代码

运行结果:

由白色的实心圆构成的路径就是我们需要的答案了

文章来源: blog.csdn.net,作者:csuzhucong,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/nameofcsdn/article/details/82528855

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(0

抱歉,系统识别当前为高风险访问,暂不支持该操作

    全部回复

    上滑加载中

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。