编程之美: 24点游戏的解法
2010-04-22 20:31
204 查看
分治法:
把A={e,f,a,b}分治成为B={e,f,a+b}, C={e,f,a-b}, D={e,f,b-a}, E={e,f,a*b}, F={e,f,a/b}, G={e,f,b/a} 这样5个元素个数等于3的集合.
这样就把A中元素运算等于24, 转化为B或C或D或E或F或G中元素运算等于24.
这展示了有关集合运算的一种方法: 元素合并, 转化为元素更少的集合.
Code:
集合的二进制表示法:
可以将元素个数为N集合的集合, 用0 ~ (2<<N)-1表示出所有子集.
从而可以利用二进制表示方便得到子集等操作.
对于本题, 还可以利用重复子问题, 减少重复计算.
Code:
把A={e,f,a,b}分治成为B={e,f,a+b}, C={e,f,a-b}, D={e,f,b-a}, E={e,f,a*b}, F={e,f,a/b}, G={e,f,b/a} 这样5个元素个数等于3的集合.
这样就把A中元素运算等于24, 转化为B或C或D或E或F或G中元素运算等于24.
这展示了有关集合运算的一种方法: 元素合并, 转化为元素更少的集合.
Code:
#include <iostream> #include <exception> #include <string> #include <stdexcept> #include <cmath> using namespace std; const int N = 4; const double RESULT = 24.0; const double DEGREE = 1e-6; double num ; string strRet ; bool pointGame(int n) { if(n == 1) { if(fabs(num[0] - RESULT) < DEGREE) { cout << strRet[0] << endl; return true; } else { return false; } } for(int i = 0; i < n; ++i) for (int j = i+1; j < n; ++j) { double tempA = num[i]; double tempB = num[j]; num[j] = num[n-1]; string expA = strRet[i]; string expB = strRet[j]; strRet[j] = strRet[n-1]; strRet[i] = '(' + expA + '+' + expB + ')'; num[i] = tempA + tempB; if(pointGame(n-1)) return true; strRet[i] = '(' + expA + '-' + expB + ')'; num[i] = tempA - tempB; if(pointGame(n-1)) return true; strRet[i] = '(' + expB + '-' + expA + ')'; num[i] = tempB - tempA; if(pointGame(n-1)) return true; strRet[i] = '(' + expA + '*' + expB + ')'; num[i] = tempA * tempB; if(pointGame(n-1)) return true; if(tempB) { strRet[i] = '(' + expA + '/' + expB + ')'; num[i] = tempA/tempB; if(pointGame(n-1)) return true; } if(tempA) { strRet[i] = '(' + expB + '/' + expA + ')'; num[i] = tempB/tempA; if(pointGame(n-1)) return true; } num[i] = tempA; num[j] = tempB; strRet[i] = expA; strRet[j] = expB; } return false; } int main() { while (scanf("%lf%lf%lf%lf", &num[0], &num[1], &num[2], &num[3]) != EOF) { for (int i = 0; i < N; ++i) { char buffer[20]; itoa((int)num[i], buffer, 10); strRet[i] = buffer; } if(!pointGame(N)) cout << "No result" << endl; } return 0; }
集合的二进制表示法:
可以将元素个数为N集合的集合, 用0 ~ (2<<N)-1表示出所有子集.
从而可以利用二进制表示方便得到子集等操作.
对于本题, 还可以利用重复子问题, 减少重复计算.
Code:
#include <iostream> #include <exception> #include <string> #include <stdexcept> #include <cmath> #include <set> using namespace std; const int N = 4; const double RESULT = 24.0; const double DEGREE = 1e-6; double num ; set<double> s[(1<<N)]; void f(int n) { if(s .size() != 0) return; for(int i = 1; i < n; ++i) if((i&n) == i) { f(i); f(n-i); for (set<double>::iterator itr1 = s[i].begin(); itr1 != s[i].end(); ++itr1) for (set<double>::iterator itr2 = s[n-i].begin(); itr2 != s[n-i].end(); ++itr2) { double a = *itr1; double b = *itr2; s .insert(a + b); s .insert(a - b); s .insert(b - a); s .insert(a * b); if(b) s .insert(a / b); if(a) s .insert(b / a); } } } int main() { for (int i = 0; i < N; ++i) { cin >> num[i]; s[(1<<i)].insert((double)num[i]); } for(int i = 1; i <= (1<<N)-1; ++i) f(i); for(set<double>::iterator itr = s[(1<<N)-1].begin(); itr != s[(1<<N)-1].end(); ++itr) if(fabs(*itr - RESULT) < DEGREE) cout << "Has an result" << endl; return 0; }
相关文章推荐
- 编程之美1.1624点游戏解法一java版
- 《编程之美》读书笔记22: 1.16 24点游戏
- 24点游戏动态规划解法(java)
- 编程之美:第一章 1.16 24点游戏
- 《编程之美》读书笔记22: 1.16 24点游戏(补充)
- 《编程之美》笔记之——24点游戏
- 编程之美————24点游戏算法
- 24点游戏的一种解法
- 编程之美24点游戏感悟
- 编程之美—24点游戏
- 关于“24点”游戏的解法
- 编程之美: 第一章 1.16 24点游戏
- 编程之美1.16——24点游戏
- 24点游戏
- NIM(1)一排石头的游戏之扩展问题解法
- 华为OJ——24点游戏算法
- 24点游戏
- 华为OJ——24点游戏算法
- 华为OJ 初级:24点游戏算法
- 编程之美大赛第一题 传话游戏