2010顶嵌杯第一题--24点运算

本文详细解析了一种计算24点问题的算法实现,包括确定运算符组合及顺序的策略,通过枚举所有可能的运算方式找到唯一解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

痛恨,当时这道题没有做出来,没有安下心认真分析。当时作出了第二道题,迷宫问题,因为以前见过类似的(具体缺乏锻炼,调试了老半天)。

题目如下:

-----------------------------------

快算24

Description

给定4个不大于10的正整数(范围1-10),要求在不改变数据先后顺序的情况下,采用加减乘除四种运算,找到一个表达式,使得最后的结果是24。

Input

4个不大于10的正整数。输入数据保证存在唯一解。

Output

不改变位置顺序,由'+','-','*','/'4个运算符和'(',')'组成的表达式

Sample Input
5 5 1 5

Sample Output
5*(5-(1/5))

---------------------------------------

认真分析,不改变位置顺序,当时被这个搞死了。但是后来发现这是个很好的限制条件,其实是简单了,而不是复杂了。

分析如下:

1)五种操作顺序

给定4个正整数,a b c d .他们的操作顺序共有六种A(3,1)
//1((a b) c) d
//2(a b) (c d)

//3(a (b c)) d

//4a ((b c) d)

//5a (b (c d))

//*6**(a b) (c d) 第六种和第二种其实同样的,不管是先算前两个 还是先算后两个 结果是一样的。
2)每个操作中都含有4中操作运算(+、-、*、/)

根据这个思想写的伪代码:

每中操作类型 根据 所操作的间隔顺序不同,传递进不同的参数

//1((a b) c) d if( findMatch(1,2,3)) //2(a b) (c d) if( findMatch(1,3,2)) //3(a (b c)) d if(findMatch(2,1,3)) //4a ((b c) d) if(findMatch(2,3,1)) //5a (b (c d)) if(findMatch(3,2,1))

int findMatch(int inter1,int inter2,int inter3) { do{ tempSum=MathChoice(number[interBefore(inter1)],number[interAfter(inter1)]) if(inter2>inter1) tempSum=MathChoice(tempSum,number[interAfter(inter2)]); else if(inter2<inter1) tempSum=MathChoice(number[interBefore(inter2)],tempSum); if(inter3>inter2) tempSum=MathChoice(tempSum,number[interAfter(inter3)]) else if(inter3<inter2) tempSum=MathChoice(number[interBefore(inter3)],tempSum); if(tempSum==24) //find the answer { return 1; } }while(); }

可以将MathChoice抽象出来,它包含4中操作运算。
#define MathChoice(i, a, b) / do { / if(i==0) / add(a,b); / else if(i==1) / minus(a,b); / else if(i==2) / mutiply(a,b); / else if(i==3) / divide(a,b); / }while(0);

根据i值不同调用不同的函数。(这里宏定义也遇到过问题,原来把操作的值返回如return add(a,b); 因为宏定义不能返回值,

所以改了,设了一个全局变量 static float tempSum=0;来记录各个操作后的结果)

间隔的顺序是1,2,3

#define interBefore(a) a-1 //当前间隔的前一个数
#define interAfter(a) a //当前间隔后一个数

3)输出 封装

因为各个操作类型都定义好了,而每个操作类型的()的位置是可以定的,变的只是操作符的类型.

因此需要记录每个间隔的操作符类型。在得到正确结果的时候将当前的操作符记录下来。+ - * / if(inter1==1) //存放间隔 的操作符,间隔位置可能不同,但是operations按第 1,2,3间隔顺序存放 operations[0]=i; else if(inter2==1) operations[1]=i; else if(inter3==1) operations[2]=i; if(inter1==2) operations[0]=j; else if(inter2==2) operations[1]=j; else if(inter3==2) operations[2]=j; if(inter1==3) operations[0]=k; else if(inter2==3) operations[1]=k; else operations[2]=k;

以下是具体的源代码:

#include <stdio.h> #include <stdlib.h> #include <math.h> float number[4]; static float tempSum=0; #define interBefore(a) a-1 #define interAfter(a) a int operations[3]; //stored 3 interOpertions between them void add(float a,float b) { tempSum=a+b; } void minus(float a,float b) { tempSum=a-b; } void mutiply(float a, float b) { tempSum= a*b; } void divide(float a,float b) { tempSum= a/b; } #define MathChoice(i, a, b) / do { / if(i==0) / add(a,b); / else if(i==1) / minus(a,b); / else if(i==2) / mutiply(a,b); / else if(i==3) / divide(a,b); / }while(0); int findMatch(int inter1,int inter2,int inter3) { tempSum=0; /* pseduo code beolow: do{ tempSum=MathChoice(number[interBefore(inter1)],number[interAfter(inter1)]) if(inter2>inter1) tempSum=MathChoice(tempSum,number[interAfter(inter2)]); else if(inter2<inter1) tempSum=MathChoice(number[interBefore(inter2)],tempSum); if(inter3>inter2) tempSum=MathChoice(tempSum,number[interAfter(inter3)]) else if(inter3<inter2) tempSum=MathChoice(number[interBefore(inter3)],tempSum); if(tempSum==24) //find the answer { return 1; } }while(); */ //have each operation kind here for(int i=0;i<4;i++) for(int j=0;j<4;j++) for(int k=0;k<4;k++) { MathChoice(i,number[interBefore(inter1)],number[interAfter(inter1)]); if(inter2>inter1) MathChoice(j,tempSum,number[interAfter(inter2)]); // else if(inter2<inter1) MathChoice(j,number[interBefore(inter2)],tempSum); if(inter3>inter2) MathChoice(k,tempSum,number[interAfter(inter3)]) else if(inter3<inter2) MathChoice(k,number[interBefore(inter3)],tempSum); if(tempSum==24) //find the answer { if(inter1==1) //存放间隔 的操作符,间隔位置可能不同,但是operations按第 1,2,3间隔顺序存放 operations[0]=i; else if(inter2==1) operations[1]=i; else if(inter3==1) operations[2]=i; if(inter1==2) operations[0]=j; else if(inter2==2) operations[1]=j; else if(inter3==2) operations[2]=j; if(inter1==3) operations[0]=k; else if(inter2==3) operations[1]=k; else operations[2]=k; return 1; } } return 0; } void outputOperations(int kind) { switch(kind) { case 0: printf("+"); break; case 1: printf("-"); break; case 2: printf("*"); break; case 3: printf("/"); break; } } int match() { //just 6 kinds, but real is just 5 kinds //1((a b) c) d if( findMatch(1,2,3)) // 1 means a and b, 2 means that then with { printf("((%d",(int)number[0]); outputOperations(operations[0]); printf("%d)",(int)number[1]); outputOperations(operations[1]); printf("%d)",(int)number[2]); outputOperations(operations[2]); printf("%d",(int)number[3]); return 1; } //2(a b) (c d) if( findMatch(1,3,2)) { printf("(%d",(int)number[0]); outputOperations(operations[0]); printf("%d)",(int)number[1]); outputOperations(operations[1]); printf("(%d",(int)number[2]); outputOperations(operations[2]); printf("%d)",(int)number[3]); return 1; } //3(a (b c)) d if(findMatch(2,1,3)) { printf("(%d",(int)number[0]); outputOperations(operations[0]); printf("(%d",(int)number[1]); outputOperations(operations[1]); printf("%d))",(int)number[2]); outputOperations(operations[2]); printf("%d",(int)number[3]); return 1; } //4a ((b c) d) if(findMatch(2,3,1)) { printf("%d",(int)number[0]); outputOperations(operations[0]); printf("((%d",(int)number[1]); outputOperations(operations[1]); printf("%d)",(int)number[2]); outputOperations(operations[2]); printf("%d)",(int)number[3]); return 1; } //5a (b (c d)) if(findMatch(3,2,1)) { printf("%d",(int)number[0]); outputOperations(operations[0]); printf("(%d",(int)number[1]); outputOperations(operations[1]); printf("(%d",(int)number[2]); outputOperations(operations[2]); printf("%d))",(int)number[3]); return 1; } //*6**(a b) (c d) is the same as before as the 2 return 0; } int main() { for(int i=0;i<4;i++) { scanf("%f",&number[i]); } match(); return 0; }

删除了伪代码注释 ,排名又往前靠了,看来代码的大小也很影响ranklist的。也就是如果有些变量名可以短的话尽量短。

基于SpringBoot的在线网络学习平台研究AI更换标第1章引言介绍基于SpringBoot的在线网络学习平台的研究背景、意义、国内外现状、论文研究方法及创新。1.1研究背景与意义阐述在线网络学习平台的重要性及其在教育领域的应用价值。1.2国内外研究现状分析当前国内外在线网络学习平台的发展状况及趋势。1.3研究方法与创新说明本研究采用的方法论和在研究过程中的创新之处。第2章相关理论技术概述SpringBoot框架、在线教育理论及相关技术基础。2.1SpringBoot框架概述介绍SpringBoot框架的特、优势及其在Web应用中的作用。2.2在线教育理论阐述在线教育的基本理念、教学模式及其与传统教育的区别。2.3相关技术基础介绍开发在线网络学习平台所需的关键技术,如前端技术、数据库技术等。第3章在线网络学习平台设计详细描述基于SpringBoot的在线网络学习平台的整体设计方案。3.1平台架构设计给出平台的整体架构图,并解释各个模块的功能及相互关系。3.2功能模块设计详细介绍平台的主要功能模块,如课程管理、用户管理、在线考试等。3.3数据库设计说明平台的数据库设计方案,包括数据表结构、数据关系等。第4章平台实现与测试阐述平台的实现过程及测试方法。4.1平台实现详细介绍平台的开发环境、开发工具及实现步骤。4.2功能测试对平台的主要功能进行测试,确保功能正常且符合预期要求。4.3性能测试对平台的性能进行测试,包括响应时间、并发用户数等指标。第5章平台应用与分析分析平台在实际应用中的效果及存在的问,并提出改进建议。5.1平台应用效果介绍平台在实际教学中的应用情况,包括用户反馈、使用情况等。5.2存在问及原因分析分析平台在运行过程中出现的问及其原因,如技术瓶颈、用户体验等。5.3改进建议与措施针对存在的问提出具体的改进建议和措施,以提高平台的性能和用户满意度
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值