24点问题C实现(2011年12月23日22:55:00)
来源:互联网 发布:mysql 触发器 同步表 编辑:程序博客网 时间:2024/05/16 13:48
问题描述
/*Description求24点问题。给定4个正整数,用算术运算符+,-,*,/将这4个正整数连接起来,使其最终结果恰为24。如果能得到24,输出Yes,否则输出No。数据输入:第一行是一个整数N(1<=N<=20),表示有多少个测试例子。以下每行为一个测试例子,每行有四个正整数。数据输出:每行输出对应测试例子的结果。Sample Input21 2 3 72 2 2 2Sample OutputYesNo*/
分析:
/**
分析:4个数中任意两个用六种运算得到一个结果,将其赋给辅助数组的第一个位置,
其他两个没有选取的赋给第二个和第三个元素;递归调用,直到得到结果,判断结果是不是24
如果不是,当传递的操作数个数为两个时,则换一个操作符试试看能不能使其得到结果为24
六种都试过后,那就得回溯到三个操作数的时候了,回溯即把辅助数组的元素还原,当然每次调用之前都把辅助数组
拷贝一份给操作数就不需要将值再赋值回赋值数组了,
为什么要回溯或者是要用到拷贝主要是因为这个公用的数组在使用时会发生变化,
当要回溯时,直接将拷贝的数据复制给它就行了
回到三个操作数那一层时,再去试试其他操作符,然后再递归调用,或者都不行,回溯到四个操作数那一层。
直到所以的操作都试了 还是得不到24 再去换其他任意两个数 继续这样的操作 知道所以的组合全部试完
仍然得不到24的话 返回false 如果有一个得到24 直接返回true 毕竟这里不是要你求所以的组合
*/
//实现
//头文件申明部分
#include <stdio.h>#include <stdlib.h>int assists[3] = {0,0,0};int calculate(int);bool judge(int *,int);
//主函数部分
int main(){ int cases,input[4],i; scanf("%d",&cases); while(cases--) { for(i=0; i<4; i++) { scanf("%d",&input[i]); } if(judge(input,4)) { printf("Yes\n"); } else { printf("No\n"); } } system("pause"); return 0;}
//六种可能的运算
int calculate(int num1,int num2,int operate){ //乘法和加法有交换律 //做除法时 除数为零和除不尽都返回30000 表示不用考虑这种情况 switch(operate) { case 1: return num1 + num2; break; case 2: return num1 - num2; break; case 3: return num1 * num2; break; case 4: return num2 - num1; break; case 5: return ((num2 != 0 && num1 % num2 == 0)?(num1/num2):10000); break; case 6: return ((num1 != 0 && num2 % num1 == 0)?num2/num1:10000); break; }}
//判断主体部分
bool judge(int *p,int count){ bool result = false; int i,j,k,n,operators[6],input[4],a=0; //先将数组拷贝一份 for(i=0; i<count; i++) { input[i] = p[i]; //printf("%d\n",p[i]); } for(i=0; i<6; i++) { operators[i] = i + 1; } for(i=0; i<count; i++) { for(j=0; j<count&&j!=i; j++) { //printf("_______________________________________\n"); for(k=0; k<6; k++) { if(calculate(input[i],input[j],operators[k]) != 10000) { //完成第一次运算 assists[0] = calculate(input[i],input[j],operators[k]); //printf("%d--------------------\n",assists[0]); if(count == 4) { bool flag = true; //给其他两个操作数赋值 for(n=0; n<count; n++) { if(n != i && n != j && flag) { assists[1] = input[n]; //printf("%d===\n",assists[1]); flag = false; continue; } else if(n != i && n != j) { assists[2] = input[n]; //printf("%d===\n",assists[2]); } else { continue; } } //调用自身,操作数个数减1 result = judge(assists,count-1); if(!result) { if(k == 5) { break; //不需要回溯,直接退出这个循环,再选取另外两个 } continue; //继续试试新的操作数 } else { return true; } } else if(count == 3) { for(n=0; n<count; n++) { if(n != i && n != j) { assists[1] = input[n]; //printf("%d===\n",assists[1]); break; } else { continue; } } if(!judge(assists,count-1)) { if(k == 5) { //assists[0] = input[0]; //回溯,返回有4个操作数时再进行判断 return false; } continue; //继续试试新的操作 } else { //printf("HelloWolrd3\n"); return true; //成功返回 } } else if(count == 2) { if(assists[0] == 24) { //printf("HelloWolrd2\n"); return true; } if(k == 5) { //assists[0] = input[0]; //回溯 //assists[1] = input[1]; return false; //返回3个操作数的时刻 } else { //printf("%d++++++++++++++++\n",a++); continue;//试试其他操作符 } } } else { continue; } } } } return false; //能到达这里 说明前面的都没有成功 最后返回false}
提交结果:AC
过程有点复杂,本人菜鸟级,求大神给出优化解!!
- 24点问题C实现(2011年12月23日22:55:00)
- 2014年7月23日 22点13分
- 2014年7月24日 23点30分
- C路历程2(原作于08年5月12日20点53分)
- C路历程2(原作于08年5月12日20点53分)
- 最长平台问题------2012年12月24日
- 2007年12月24日(22、23日没写)
- 2014年7月22日 6点30分
- 2011年9月29日1点15分
- 2011年10月3日13点20时
- 2011年10月6日3点39分
- 2014年7月24日 5点57分
- 2014年7月24日 9点44分
- 2014年7月23日 0点35分
- 2014年7月23日 6点15分
- 2017年2月27日23点34分
- NYOJ-24-素数距离问题-2013年10月12日14:56:23
- 年,月,日获取时间点
- C#匿名方法的用法
- 中国培训师竞争力排行榜获奖名单
- Sencha touch(手機網站程式框架)相關資源
- Linux驱动模型的基本数据结构kobject介绍
- 给明年依然年轻的我们
- 24点问题C实现(2011年12月23日22:55:00)
- 黑马程序员_继承
- 模拟电路点滴一
- 三个桶,分别为19升(空)、13升(满)、7升(满),请问最少多少步可以做到两个10升的??
- USB2.0接口差分信号线布线设计
- 其他书单
- 锂电池正确充电方法及日常使用注意事项
- datastage抽取定界文本文件时报错
- one typical kickstart file for FC16