P1236 算24点
题目链接
题目描述
几十年前全世界就流行一种数字游戏,至今仍有人乐此不疲.在中国我们把这种游戏称为“算24点”。您作为游戏者将得到4个1~9之间的自然数作为操作数,而您的任务是对这4个操作数进行适当的算术运算,要求运算结果等于24。
您可以使用的运算只有:+,-,,/,您还可以使用()来改变运算顺序。注意:所有的中间结果须是整数,所以一些除法运算是不允许的(例如,(22)/4是合法的,2*(2/4)是不合法的)。下面我们给出一个游戏的具体例子:
若给出的4个操作数是:1、2、3、7,则一种可能的解答是1+2+3*7=24。
输入格式
只有一行,四个1到9之间的自然数。
输出格式
如果有解的话,只要输出一个解,输出的是三行数据,分别表示运算的步骤。其中第一行是输入的两个数和一个运算符和运算后的结果,第二行是第一行的结果和一个输入的数据、运算符、运算后的结果,或者是另外两个数的输出结果;第三行是前面的结果第二行的结果或者剩下的一个数字、运算符和“=24”。如果两个操作数有大小的话则先输出大的。
如果没有解则输出“No answer!”
如果有多重合法解,输出任意一种即可。
注:所有运算结果均为正整数
输入输出样例
输入
1 2 3 7
输出
2+1=3
7*3=21
21+3=24
想法
显然就是要组成一个表达式计算a?b?c?d是否等于24(至于括号可以在表达式出来之后再加);
判定其是否等于24,然后再输出计算过程,所以我的想法就是在
递归的过程中把算式记录下来;
方法如下
//定义一个结构体,保存数字和符号
// 1-> +
// 2-> -
// 3-> *
// 4-> /
struct node{
int num,fh;
}cun[10];
在递归的过程中选择数据和符号,得到表达式。
int a[10];//用于存储4个数。
int book[10];
void dfs(int s){
for(int i=1;i<=4;i++){
if(book[i])
continue;
book[i]=1;
cun[s].num=a[i];
for(int j=1;j<=4;j++){
cun[s].fh=j;
dfs(s+1);
}
book[i]=0;
}
}
在得到表达式之后,我们就可以加括号,来计算结果。
有4 种加括号的方法(为保证不重不漏,从不加括号到一个括号再到两个,三个)
1.a?b?c?d
2.(a?b?c)?d
3.a?(b?c?d)
4.(a?b)?c?d
5.a?(b?c)?d
6.a?b?(c?d)
因为加减乘除算数的时候有优先级,前六种在光有一个算式外加一个括号的条件下,还要确定另外两个符号的优先级,在判定优先级的过程中,实际上是相当于又给算式加了括号,会和后面的算式重复,故前六种无效。
7.(a?b)?(c?d)
8.((a?b)?c)?d
9.(a?(b?c))?d
10.a?((b?c)?d)
11.a?(b?(c?d))
后五种中8,9,10,11其实是等效的,也就相当于只有
7和8两种加括号的方式。
// 1 -> +
// 2 -> -
// 3 -> *
// 4 -> /
int js(int a, int b, int k) {
if (k == 1)
return a + b;
if (k == 2)
return a - b;
if (k == 3)
return a *b;
if (k == 4) {
if (b == 0) return -1000;
if (a % b != 0||a<b)
return -10000;
else return a/b;
}
}
void dfs(int s){
if(s==5){
int ans=cun[1].num;
//按方案8计算
for(int i=1;i<=3;i++)
ans=(ans,cun[i+1].num,cun[i].fh);
//按方案7计算
if(ans!=24){
int x=js(cun[1].num,cun[2].num,cun[1].fh);
int y=js(cun[3].num,cun[4].num,cun[3].fh);
int z=js(x,y,cun[2].fh);
}
}
}
最后附上完整代码
#include<bits/stdc++.h>
using namespace std;
int a[10],book[10],flag=0;
struct node {
int num;
int fh;
}cun[10];
// 1 -> +
// 2 -> -
// 3 -> *
// 4 -> /
int js(int a, int b, int k) {
if (k == 1)
return a + b;
if (k == 2)
return a - b;
if (k == 3)
return a *b;
if (k == 4) {
if (b == 0) return -1000;
if (a % b != 0||a<b)
return -10000;
else return a/b;
}
}
void sc(int a,int b,int k) {
if (k == 1)
printf("%d+%d=%d\n", max(a, b), min(a, b), a + b);
if (k == 2)
printf("%d-%d=%d\n", a, b, a - b);
if (k == 3)
printf("%d*%d=%d\n", max(a, b), min(a, b), a * b);
if (k == 4)
printf("%d/%d=%d\n", a, b, a / b);
}
void dfs(int s) {
if (s == 5) {
int ans = cun[1].num;
for (int i = 1; i <= 3; i++)
ans=js(ans, cun[i + 1].num, cun[i].fh);
if (ans != 24) {
int x = js(cun[1].num,cun[2].num,cun[1].fh);
int y = js(cun[3].num,cun[4].num,cun[3].fh);
if (js(x, y, cun[2].fh) == 24) {
flag = 1;
sc(cun[1].num, cun[2].num, cun[1].fh);
sc(cun[3].num, cun[4].num, cun[3].fh);
sc(x, y, cun[2].fh);
return;
}
}
if (ans == 24) {
flag = 1;
int sum = cun[1].num;
for (int i = 1; i <= 3; i++) {
int k = cun[i].fh;
sc(sum, cun[i + 1].num, k);
sum=js(sum, cun[i + 1].num, k);
}
}
return;
}
for (int i = 1; i <= 4; i++) {
if (book[i]) continue;
book[i] = 1;
cun[s].num = a[i];
for (int j = 1; j <= 4; j++) {
cun[s].fh = j;
dfs(s + 1);
if (flag)
return;
}
book[i] = 0;
}
}
int main() {
memset(book, 0, sizeof(book));
for (int i = 1; i <= 4; i++)
scanf("%d", &a[i]);
dfs(1);
if (flag == 0)
printf("No answer!");
}