puzzle(0334)双面数局

目录

一,双面数局

二,计算机求解

1,交换公式

2,通用操作

3,n=2

4,n=3

5,n=4

三,高阶场景

1,通用操作

2,n=5

3,n=6


一,双面数局

最强大脑 同款项目

二,计算机求解

1,交换公式

参考交换公式自动推导V6

2,通用操作


vector<Opt> getOpts(int n)
{
	vector<int>v0;
	for (int i = 0; i < n*n * 2; i++)v0.push_back(i);
	vector<Opt>ans;
	for (int i = 0; i < n; i++) {
		string optName = "第";
		optName += std::to_string(i + 1);
		optName += "行往右";
		vector<int>v = v0;
		int s1 = i * n, s2 = i * n + n * n;
		vector<int>nums;
		for (int i = s1; i < s1 + n; i++)nums.push_back(i);
		for (int i = s2; i < s2 + n; i++)nums.push_back(i);
		for (int i = 0; i < nums.size(); i++)v[nums[(i + 1) % nums.size()]] = nums[i];
		Opt opt{ { v } ,optName };
		ans.push_back(opt);
	}
	for (int i = 0; i < n; i++) {
		string optName = "第";
		optName += std::to_string(i + 1);
		optName += "列往下";
		vector<int>v = v0;
		int s1 = i, s2 = n * n * 2 - i - 1;
		vector<int>nums;
		for (int i = s1; i < s1 + n * n; i += n)nums.push_back(i);
		for (int i = s2; i > s2 - n * n; i -= n)nums.push_back(i);
		for (int i = 0; i < nums.size(); i++)v[nums[(i + 1) % nums.size()]] = nums[i];
		Opt opt{ { v } ,optName };
		ans.push_back(opt);
	}
	return ans;
}

3,n=2

int main()
{
	int n = 2;
	CubeBlock block1(0, n * n * 2);
	vector<CubeBlock>b = vector<CubeBlock>{ block1 };
	vector<Opt> v = getOpts(n);
	CubeOpt op1(b, v[0]);
	CubeOpt op2(b, v[1]);
	CubeOpt op3(b, v[2]);
	CubeOpt op4(b, v[3]);
	vector<CubeOpt>opts = { op1,op2,op3,op4 };
	for (int i = 0; i < opts.size(); i++)mans[i] = opts[i].getName();
	Cube cube(b, opts);
	cube.bfs(0, 2, 2);
	return 0;
}

输出:

2,1,0,3,4,5,6,7,
0第1行往右 0第1行往右 1第2行往右 2第1列往下 0第1行往右 1第2行往右 2第1列往下 1第2行往右 2第1列往下 0第1行往右 3第2列往下

这是交换0和2的公式

4,n=3

int main()
{
	int n = 3;
	CubeBlock block1(0, n * n * 2);
	vector<CubeBlock>b = vector<CubeBlock>{ block1 };
	vector<Opt> v = getOpts(n);
	CubeOpt op1(b, v[0]);
	CubeOpt op2(b, v[1]);
	CubeOpt op3(b, v[2]);
	CubeOpt op4(b, v[3]);
	CubeOpt op5(b, v[4]);
	CubeOpt op6(b, v[5]);
	vector<CubeOpt>opts = { op1,op2,op3,op4,op5,op6 };
	for (int i = 0; i < opts.size(); i++)mans[i] = opts[i].getName();
	Cube cube(b, opts);
	cube.bfs(0, 2, 2);
	return 0;
}

输出:

0,1,7,3,4,5,6,2,8,9,10,11,12,13,14,15,16,17,
0第1行往右 0第1行往右 4第2列往下 1第2行往右 1第2行往右 1第2行往右 4第2列往下 4第2列往下 0第1行往右 0第1行往右 0第1行往右 0第1行往右 0第1行往右 1第2行往右 1第2行往右 0第1行往右 0第1行往右 0第1行往右 0第1行往右 0第1行往右 1第2行往右

这是交换2和7的公式

化简结果:

第1行往右 *2
第2列往下
第2行往右*3
第2列往下*2
第1行往左*2
第2行往右*3

5,n=4

代码1:略

运行结果:得到0 18 19 23交换的公式(不是1个4阶置换,而是2个2阶置换)

代码2:

int main()
{
	int n = 4;
	CubeBlock block1(0, n * n * 2);
	vector<CubeBlock>b = vector<CubeBlock>{ block1 };
	vector<Opt> v = getOpts(n);
	CubeOpt op1(b, v[0]);
	CubeOpt op2(b, v[1]);
	CubeOpt op3(b, v[2]);
	CubeOpt op4(b, v[3]);
	CubeOpt op5(b, v[4]);
	CubeOpt op6(b, v[5]);
	CubeOpt op7(b, v[6]);
	CubeOpt op8(b, v[7]);
	Opt opt9{ { {19,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,23,0,20,21,22,18,24,25,26,27,28,29,30,31} } ,"【1下1右1上1左】" };
	CubeOpt op9(b, opt9);
	vector<CubeOpt>opts = { op1,op2,op3,op4,op5,op6,op7,op8,op9 };
	for (int i = 0; i < opts.size(); i++)mans[i] = opts[i].getName();
	Cube cube(b, opts);
	cube.bfs(0, 2, 3);
	return 0;
}

输出:

0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,21,19,20,22,18,23,24,25,26,27,28,29,30,31,
1第2行往右 6【1下1右1上1左】 1第2行往右 6【1下1右1上1左】 1第2行往右 1第2行往右 1第2行往右 1第2行往右 1第2行往右 1第2行往右

这是18-22-21三者轮换(顺时针旋转)的公式

化简结果:

第2行往右 
【1下1右1上1左】 
第2行往右 
【1下1右1上1左】 
第2行往左*2

我们把这个公式记作三轮换公式

代码3:

int main()
{
	int n = 4;
	CubeBlock block1(0, n * n * 2);
	vector<CubeBlock>b = vector<CubeBlock>{ block1 };
	vector<Opt> v = getOpts(n);
	CubeOpt op1(b, v[0]);
	CubeOpt op2(b, v[1]);
	CubeOpt op3(b, v[2]);
	CubeOpt op4(b, v[3]);
	CubeOpt op5(b, v[4]);
	CubeOpt op6(b, v[5]);
	CubeOpt op7(b, v[6]);
	CubeOpt op8(b, v[7]);
	Opt opt9{ { {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,21,19,20,22,18,23,24,25,26,27,28,29,30,31} } ,"三轮换" };
	CubeOpt op9(b, opt9);
	vector<CubeOpt>opts = { op2,op9 };
	for (int i = 0; i < opts.size(); i++)mans[i] = opts[i].getName();
	Cube cube(b, opts);
	cube.bfs(0, 2, 2);
	return 0;
}

输出:

0,1,2,3,4,6,5,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
0第2行往右 1三轮换 0第2行往右 0第2行往右 1三轮换 0第2行往右 0第2行往右 0第2行往右 1三轮换 0第2行往右 0第2行往右 1三轮换 0第2行往右

这是交换5和6的公式

化简结果:

第2行往右
【2右1下1右1上1左】 *4 
第2行往右
【2右1下1右1上1左】 *4  
第2行往左

其中,2右就是第2行往右,以此类推。

同理,还有交换4和7的公式

第2行往右*3 
【1下1右1上1左】 
第2行往右 
【1下1右1上1左】 
第2行往右 *2
【1下1右1上1左】 
第2行往右 
【1下1右1上1左】 
第2行往左*2
【1下1右1上1左】 
第2行往右 
【1下1右1上1左】
第2行往右 *2
【1下1右1上1左】 
第2行往右 
【1下1右1上1左】 
 第2行往右 
【1下1右1上1左】 
第2行往右 
【1下1右1上1左】 
第2行往左*2

三,高阶场景

前面的校验,基本上已经形成固定的模式了,只需要数字改一改就能得到高阶的公式了。

和魔方不同的是,魔方是公式本身进行微调即可得到新公式,而双面数局是产生n=k的公式的代码微调即可得到产生n=k+1的公式的代码,但n=k的公式和n=k+1的公式之间差别还是挺大的。

1,通用操作

我们把“1下1右1上1左”这个小公式进行参数化,避免手动输入置换表


vector<Opt> getOpts(int n)
{
	vector<int>v0;
	for (int i = 0; i < n*n * 2; i++)v0.push_back(i);
	vector<Opt>ans;
	for (int i = 0; i < n; i++) {
		string optName = "第";
		optName += std::to_string(i + 1);
		optName += "行往右";
		vector<int>v = v0;
		int s1 = i * n, s2 = i * n + n * n;
		vector<int>nums;
		for (int i = s1; i < s1 + n; i++)nums.push_back(i);
		for (int i = s2; i < s2 + n; i++)nums.push_back(i);
		for (int i = 0; i < nums.size(); i++)v[nums[(i + 1) % nums.size()]] = nums[i];
		Opt opt{ { v } ,optName };
		ans.push_back(opt);
	}
	for (int i = 0; i < n; i++) {
		string optName = "第";
		optName += std::to_string(i + 1);
		optName += "列往下";
		vector<int>v = v0;
		int s1 = i, s2 = n * n * 2 - i - 1;
		vector<int>nums;
		for (int i = s1; i < s1 + n * n; i += n)nums.push_back(i);
		for (int i = s2; i > s2 - n * n; i -= n)nums.push_back(i);
		for (int i = 0; i < nums.size(); i++)v[nums[(i + 1) % nums.size()]] = nums[i];
		Opt opt{ { v } ,optName };
		ans.push_back(opt);
	}
	string optName = "1下1右1上1左";
	vector<int>v = v0;
	v[0] = n * n + n - 1, v[n * n + n - 1] = 0;
	v[n * n + n - 2] = n * n + n * 2 - 1, v[n * n + n * 2 - 1] = n * n + n - 2;
	Opt opt{ { v } ,optName };
	ans.push_back(opt);
	return ans;
}

2,n=5

代码1:

int main()
{
	int n = 5;
	CubeBlock block1(0, n * n * 2);
	vector<CubeBlock>b = vector<CubeBlock>{ block1 };
	vector<Opt> v = getOpts(n);
	CubeOpt op1(b, v[0]);
	CubeOpt op2(b, v[1]);
	CubeOpt op3(b, v[2]);
	CubeOpt op4(b, v[3]);
	CubeOpt op5(b, v[4]);
	CubeOpt op6(b, v[5]);
	CubeOpt op7(b, v[6]);
	CubeOpt op8(b, v[7]);
	CubeOpt op9(b, v[8]);
	CubeOpt op10(b, v[9]);
	CubeOpt op11(b, v[10]);
	vector<CubeOpt>opts = { op1,op2,op11 };
	for (int i = 0; i < opts.size(); i++)mans[i] = opts[i].getName();
	Cube cube(b, opts);
	cube.bfs(0, 2, 3);
	return 0;
}

输出:

0,1,2,3,4,28,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,34,29,30,31,32,33,5,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,
1第2行往右 1第2行往右 1第2行往右 1第2行往右 1第2行往右 1第2行往右 1第2行往右 1第2行往右 1第2行往右 21下1右1上1左 1第2行往右 21下1右1上1左

这是一个三轮换的公式。

化简结果:

第2行往左 
【1下1右1上1左】 
第2行往右
【1下1右1上1左】 

代码2:

int main()
{
	int n = 5;
	CubeBlock block1(0, n * n * 2);
	vector<CubeBlock>b = vector<CubeBlock>{ block1 };
	vector<Opt> v = getOpts(n);
	CubeOpt op1(b, v[0]);
	CubeOpt op2(b, v[1]);
	CubeOpt op3(b, v[2]);
	CubeOpt op4(b, v[3]);
	CubeOpt op5(b, v[4]);
	CubeOpt op6(b, v[5]);
	CubeOpt op7(b, v[6]);
	CubeOpt op8(b, v[7]);
	CubeOpt op9(b, v[8]);
	CubeOpt op10(b, v[9]);
	CubeOpt op11(b, v[10]);
	Opt opt{ { {0,1,2,3,4,28,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,34,29,30,31,32,33,5,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49} } ,"三轮换" };
	CubeOpt op12(b, opt);
	vector<CubeOpt>opts = { op2,op12 };
	for (int i = 0; i < opts.size(); i++)mans[i] = opts[i].getName();
	Cube cube(b, opts);
	cube.bfs(0, 2, 2);
	return 0;
}

输出1:

0,1,2,3,4,5,6,8,7,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,
0第2行往右 0第2行往右 1三轮换 0第2行往右 0第2行往右 1三轮换 0第2行往右 0第2行往右 1三轮换 0第2行往右 0第2行往右 0第2行往右 1三轮换 0第2行往右 0第2行往右 1三轮换

这是交换7和8的公式

化简结果:

【2右1下1右1上1左】 *6 
 第2行往右 
【2右1下1右1上1左】 *4

输出2:

0,1,2,3,4,5,6,9,8,7,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,
0第2行往右 0第2行往右 1三轮换 0第2行往右 0第2行往右 1三轮换 0第2行往右 0第2行往右 1三轮换 0第2行往右 1三轮换 1三轮换 0第2行往右 0第2行往右 1三轮换 0第2行往右 0第2行往右 1三轮换
这是交换7和9的公式

化简结果:

【2右1下1右1上1左】 *6 
第2行往左
【2右1下1右1上1左】 *2
第2行往左*2
【2右1下1右1上1左】 *6

3,n=6

公式推导方法同上。

交换10和11的公式

【2右1下1右1上1左】 *6  
第2行往右  
【2右1下1右1上1左】 *6

其中,2右就是第2行往右,以此类推。

PS:复原之后,正面第一行是0 1 2 3 4 5,第二行是6 7 8 9 10 11,换句话说上面这个公式就是交换正面第二行右边的2个格子。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值