第 1 题 速算游戏
源程序名 fun.pas|c|cpp
输入文件名 fun.in
输出文件名 fun.out
时间限制 1s/testcase
空间限制 32MB
问题描述
jyx和cyy打赌,比谁24点算得快,算得慢的那个人请客。24点的规则是这样的:给定4
个1..9的整数,用括号改变运算顺序,通过加、减、乘、除通的一系列运算,得到整数24,
注意所有中间结果必须是整数(例如(2*2)/4是允许的,而2*(2/4)是不允许的)。为了赢得
这个比赛,请写一个程序帮助我作弊,快速地计算出24点。
输入数据
一行 4 个整数,为给定的 4 个数字。输入数据保证有解。
输出数据
一行,以字符串的形式输出结果,注意将每一步的运算的括号补齐(例如(3+5)+6和
3*(5+6))如果有多种解答,输出字典顺序最小的一个。
样例输入
2 3 5 7
样例输出
源程序名 fun.pas|c|cpp
输入文件名 fun.in
输出文件名 fun.out
时间限制 1s/testcase
空间限制 32MB
问题描述
jyx和cyy打赌,比谁24点算得快,算得慢的那个人请客。24点的规则是这样的:给定4
个1..9的整数,用括号改变运算顺序,通过加、减、乘、除通的一系列运算,得到整数24,
注意所有中间结果必须是整数(例如(2*2)/4是允许的,而2*(2/4)是不允许的)。为了赢得
这个比赛,请写一个程序帮助我作弊,快速地计算出24点。
输入数据
一行 4 个整数,为给定的 4 个数字。输入数据保证有解。
输出数据
一行,以字符串的形式输出结果,注意将每一步的运算的括号补齐(例如(3+5)+6和
3*(5+6))如果有多种解答,输出字典顺序最小的一个。
样例输入
2 3 5 7
样例输出
(((3*5)+2)+7)
容易想到要生成全排列,但是又容易被括号误导。
但是我们来单独讨论一下括号,无非就是下面三种情况。
(((a?b)?c)?d)、(((a?b)?(c?d))、(a?(b?(c?d)))
但是考虑到括号的ASCII码是最小的,因此第三种可以果断排除,
因为它们可以有完全相同的运算,但是明显第一种比第三种的字典序小。
一开始差点打错,差点按照+、-、*、/来了。注意/要单独考虑,因为不能有除不尽的情况。
ZQZ犯了一个错,他先生成数字的全排列,再生成符号的全排列,因此不能保证字典序最小。
所以必须间隔搜索。
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <cstdlib>
using std::sort;
const char hash[5] = {0,'*','+','-','/'};
long num[5];
long stack1[20];
long stack2[20];
long getint()
{
long rs=0;bool sgn=1;char tmp;
do tmp = getchar();
while (!isdigit(tmp)&&tmp!='-');
if (tmp=='-'){tmp=getchar();sgn=0;}
do rs=(rs<<3)+(rs<<1)+tmp-'0';
while (isdigit(tmp=getchar()));
return sgn?rs:-rs;
}
long calc(long a,long b,long c)
{
switch (c)
{
case 1:
return a*b;
case 2:
return a+b;
case 3:
return a-b;
case 4:
if (!(a % b))
return a/b;
else
return -0x3f3f3f3f;
}
return -0x3f3f3f3f;
}
bool used[5];
void dfs(long u,bool o)
{
if (u == 8)
{
long rs = calc(stack1[1],stack1[3],stack2[2]);
if (rs == -0x3f3f3f3f) return;
rs = calc(rs,stack1[5],stack2[4]);
if (rs == -0x3f3f3f3f) return;
rs = calc(rs,stack1[7],stack2[6]);
if (rs == -0x3f3f3f3f) return;
if (rs == 24)
{
printf("(((%ld%c%ld)%c%ld)%c%ld)",stack1[1],hash[stack2[2]],stack1[3],hash[stack2[4]],stack1[5],hash[stack2[6]],stack1[7]);
exit(0);
}
return;
}
if (o)
{
for (long i=1;i<5;i++)
{
if (!used[i])
{
stack1[u] = num[i];
used[i] = u;
dfs(u+1,!o);
used[i] = 0;
}
}
}
else
{
for (long i=1;i<5;i++)
{
stack2[u] = i;
dfs(u+1,!o);
}
}
}
void dfs2(long u,bool o)
{
if (u == 8)
{
long rs1 = calc(stack1[1],stack1[3],stack2[2]);
if (rs1 == -0x3f3f3f3f) return;
long rs2 = calc(stack1[5],stack1[7],stack2[6]);
if (rs2 == -0x3f3f3f3f) return;
long rs = calc(rs1,rs2,stack2[4]);
if (rs == -0x3f3f3f3f) return;
if (rs == 24)
{
printf("((%ld%c%ld)%c(%ld%c%ld))",stack1[1],hash[stack2[2]],stack1[3],hash[stack2[4]],stack1[5],hash[stack2[6]],stack1[7]);
exit(0);
}
return;
}
if (o)
{
for (long i=1;i<5;i++)
{
if (!used[i])
{
stack1[u] = num[i];
used[i] = 1;
dfs2(u+1,!o);
used[i] = 0;
}
}
}
else
{
for (long i=1;i<5;i++)
{
stack2[u] = i;
dfs2(u+1,!o);
}
}
}
int main()
{
freopen("fun.in","r",stdin);
freopen("fun.out","w",stdout);
num[1] = getint();
num[2] = getint();
num[3] = getint();
num[4] = getint();
sort(num+1,num+5);
dfs(1,true);
dfs2(1,true);
return 0;
}