今天看了某葱同学的人人日志…其实这个奇葩的24点游戏还挺有意思的……
这张图是输出的结果……
原题网址:
http://blog.renren.com/blog/248552164/820688259
http://blog.renren.com/share/319323058/12649683349?from=0101010202&ref=hotnewsfeed&sfet=102&fin=35&ff_id=319323058
国际惯例,先粘代码再粘题……
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;
const int NUM = 4;
const int TARGET = 24;
const int MAX_NUM = 14;
int number[NUM], counter;
bool flag;
string formula[NUM];
ofstream fout("result.txt");
bool Deal(int);
int main()
{
for(int mark_1 = 1; mark_1 != MAX_NUM; ++mark_1)
{
number[0] = mark_1;
for(int mark_2 = mark_1; mark_2 != MAX_NUM; ++mark_2)
{
number[1] = mark_2;
for(int mark_3 = mark_2; mark_3 != MAX_NUM; ++mark_3)
{
number[2] = mark_3;
for(int mark_4 = mark_3; mark_4 != MAX_NUM; ++mark_4)
{
number[3] = mark_4;
counter = 0;
flag = false;
fout << "Case ";
for(int i = 0; i != NUM; ++i)
{
fout << number[i] << " ";
char buffer[10];
itoa(number[i], buffer, 10);
formula[i] = buffer;
}
fout << endl;
Deal(NUM);
if(flag == false)
{
fout << "There is no way to do that!" << endl;
}
else
{
fout << "The number of solution is " << counter << endl;
}
}
}
}
}
return 0;
}
bool Deal(int depth)
{
if(depth == 1)
{
if(number[0] == TARGET)
{
fout << formula[0] << endl;
flag = true;
counter++;
return true;
}
else
{
return false;
}
}
for(int i = 0; i != depth; ++i)
{
for(int j = i + 1; j != depth; ++j)
{
int buf_a, buf_b;
string form_a, form_b;
buf_a = number[i];
buf_b = number[j];
number[j] = number[depth - 1];
form_a = formula[i];
form_b = formula[j];
formula[j] = formula[depth - 1];
formula[i] = '(' + form_a + '&' + form_b + ')';
number[i] = buf_a & buf_b;
Deal(depth - 1);
formula[i] = '(' + form_a + '|' + form_b + ')';
number[i] = buf_a | buf_b;
Deal(depth - 1);
formula[i] = '(' + form_a + '^' + form_b + ')';
number[i] = buf_a ^ buf_b;
Deal(depth - 1);
formula[i] = '(' + form_a + '>' + '>' + form_b + ')';
number[i] = buf_a >> buf_b;
Deal(depth - 1);
formula[i] = '(' + form_a + '<' + '<' + form_b + ')';
number[i] = buf_a << buf_b;
Deal(depth - 1);
formula[i] = '(' + form_b + '>' + '>' + form_a + ')';
number[i] = buf_b >> buf_a;
Deal(depth - 1);
formula[i] = '(' + form_b + '<' + '<' + form_a + ')';
number[i] = buf_b << buf_a;
Deal(depth - 1);
number[i] = buf_a;
number[j] = buf_b;
formula[i] = form_a;
formula[j] = form_b;
}
}
return true;
}
嗯……题目如下……
什么是按位24点?
按位24点就是一种原创的24点玩法,顾名思义,就是通过一定的运算,将4个数字得到24的结果。只不过这里的运算指的不是四则运算,而是位运算或移位运算。
按位24点的规则是什么?
按位24点允许使用位运算符(&、|和^)、移位运算符(<<和>>),不允许使用四则运算(加减乘除),更不允许其它莫名其妙的运算(幂指对、求导、阶乘、三角函数、时钟等等),允许使用括号。例如,以下是一个合法的算式:
(1|2)<<(1|2)=24
上式的含义是分别将两个1(00001)和2(00010)取按位或(|),得到3(00011),将3(00011)左移三位得到24(11000)。规则大致是这样,但是对于大多数情况这样的算式还是很难得到的,毕竟二进制离生活有点远……
为什么不允许用四则运算?
就是不能用。没有为什么。
为什么没有非运算(~)和负数?
因为负数的二进制表示存在争议。尽管一般来说,计算机用(1……1111)表示-1,引入负数也是可以的。但是不难发现,同时引入非和取负就提供了一种耍赖的方法,譬如说我可以用1得到任何数:-~1=2;-~-~1=3;……这个困难也许是可以克服的,但目前看来,还是没有必要引入非运算。
玩这个游戏有什么用?
完全没有用。顶多让你熟悉一下二进制……主要是闲的蛋疼……
这个脑残游戏是怎么被想出来的?
前段时间流行用0、0、0、0;1、1、1、1算24点的奇葩算法,我“自然”就想到了这种规则,顺带一提的是,我想出的一种做法是(1-~1)<<(1-~1),很明显它有一种简洁和对称美,但是其实并不符合这里的要求。
这个游戏好玩吗?找谁和我玩?
我有充分的理由相信,这个游戏你是绝对找不到人陪你玩的。你就自己一个人角落里玩去吧。
这个游戏有窍门吗?
经过本人几个小时的实践,窍门绝对是有的。就像所谓的“三八二十四”、“四六二十四”一样,我们也有3<<3,6<<2等等。另一方面,最终得到11000要求在第四、五位上各有一个1,可以先凑11再移位,有时候也可以分别凑出来取或。当然最后,我建议用“二进制扑克牌”(有这种东西吗?)玩这个游戏。
每种组合都能算出来吗?
答案显然是否定的。例如,前面提到的1、1、1、1就没算出来。另外经过多次实践,我发现算的牌在6以上时简直在挑战思维极限……所幸的是,6以内的情况大多数时候还是能算出来的。
下表给出了13以内的部分结果:
(注:<<*表示交换两边次序,例如 a<<*b = b<<a,>>*同理)