赞
踩
在这本书中要求了表达式中数字的顺序不能改变,所以在7.7节 中提供的算法不具有普遍适应性,但是算法的思路还是很简单并且清晰。不需要多动脑袋。在他的基础上,可以轻易的扩展成一般的算法。
一些比较难的24点计算
1 3 9 10
1 4 5 6
1 5 5 5
2 7 10 10
3 3 7 7
3 3 8 8
【1】最开始是4个数,A、B、C、D。
【2】从4个数中选择两个数,例如 A 和 B 。
【3】将两个数进行运算,R1 = A OP B
【4】运算结果 R1 和 剩余的数字进行运算,R1、C、D
【5】从三个数中选择任意两个数进行运算
【6】继续运算,只至一个数字
【7】用递归方法,计算结果是否为24 ,很容易,但是要输出一条完整的表达式,很复杂,因为其简单的计算思路,值得笔记下来。表达式应该还有需要深思的地方…
#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<vector> #include <string> #include <map> using namespace std; string ops[] = { "#","+","-","*","/","-","/" }; map <string, vector<string> > maps; static int counts = 3; string num_string( double n ) { char buf[10]; sprintf( buf, "%g", n ); return string( buf ); } double cal( double x, double y, int op ) { switch( op ) { case 1:return x + y; case 2:return x - y; case 3:return x * y; case 4: { if( y == 0 ) return -1000; return x / y; } default: return -1000; } } void findKeys( map <string, vector<string> > &m, string &v ) { map <string, vector<string> >::iterator it; it = m.find( v ); if( it != m.end() && counts > 0 ) { counts--; cout << "("; for( int i = 0; i < 3; i++ ) { findKeys( m, it->second[i] ); } cout << ")"; } else { cout << v; } } bool is24( vector<double> a ) { bool find = false; if( a.size() == 1 ) return fabs( a[0] - 24 ) < 10E-5; for( int i = 0; i < a.size(); i++ ) { vector<double> b( a ); b.erase( b.begin() + i ); for( int j = 0; j < b.size(); j++ ) { vector<double> c( b ); c.erase( c.begin() + j ); for( int op = 1; op <= 4; op++ ) { vector<double> d( c ); double r = cal( a[i], b[j], op ); if( r < 0 ) continue; else d.push_back( r ); if( is24( d ) ) { find = true; vector<string> res; res.push_back( num_string( a[i] ) ); res.push_back( ops[op] ); res.push_back( num_string( b[j] ) ); maps[num_string( r )] = res; return true; } } } } return false; } int main() { vector<double> a( 4, 0 ); while( cin >> a[0] >> a[1] >> a[2] >> a[3] ) { maps.clear(); counts = 3; if( is24( a ) ) { cout << "true" << endl; string s( "24" ); findKeys( maps, s); cout << " = 24" << endl; } else cout << "false" << endl; } }
【1】四个数, 穷举 A、B、C、D
【2】三个符号,穷举 +、-、×、÷
【3】两种模式
【3.1】组成表达式,((A OP1 B) OP2 C ) OP3 D
【3.2】组成表达式,(A OP1 B) OP3 (C OP2 D)
【4】注意:减法和除法两个数字交换顺序后,会有不同结果,所以四则运算要分成6种。
对于减法,要检查是否为负数;对于除法,还要检查除数是否为0。
此时每一个数字和符号都已确定,可直接组合成完整的表达式。
#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<vector> #include <string> #include <map> using namespace std; string ops[] = { "#","+","-","*","/","-","/" }; string num_string( double n ) { char buf[10]; sprintf( buf, "%g", n ); return string( buf ); } double cal( double x, double y, int op ) { switch( op ) { case 1:return x + y; case 2:return x - y; case 3:return x * y; case 4: { if( y == 0 ) return -1000; return x / y; } case 5: return y - x; case 6: { if( x == 0 ) return -1000; return y / x; } default: return -1000; } } bool findString( vector<string> &vec, const string &str ) { for( const string var : vec ) { if( var == str ) return true; } return false; } bool is24( vector<double> a ) { vector < string > results; bool find = false; string res; //可以考虑使用逆波兰表达式,脱去括号,求得最终的表达式,加入表达式集,去除相同的部分 for( int A = 0; A < 4; A++ ) { for( int B = 0; B < 4; B++ ) { if( B == A ) continue; for( int C = 0; C < 4; C++ ) { if( C == A || C == B ) continue; for( int D = 0; D < 4; D++ ) { if( D == A || D == B || D == C ) continue; for( int op1 = 1; op1 <= 4; op1++ ) for( int op2 = 1; op2 <= 6; op2++ ) for( int op3 = 1; op3 <= 6; op3++ ) { double r1 = cal( a[A], a[B], op1 ); // (A op1 B) || (B op1 A) if( r1 < 0 ) continue; double r21 = cal( r1, a[C], op2 ); // (r1 op2 C) || (C op2 r1) double r31 = cal( r21, a[D], op3 ); // (r21 op2 D) || (D op2 r21) if( fabs( r31 - 24 ) < 10E-5 && ( r21 >= 0 ) ) { //cout << "r31\n"; find = true; if( op1 < 5 ) res = "(" + num_string( a[A] ) + ops[op1] + num_string( a[B] ) + ")"; else res = "(" + num_string( a[B] ) + ops[op1] + num_string( a[A] ) + ")"; if( op2 < 5 ) res = "(" + res + ops[op2] + num_string( a[C] ) + ")"; else res = "(" + num_string( a[C] ) + ops[op2] + res + ")"; if( op3 < 5 ) res = res + ops[op3] + num_string( a[D] ); else res = num_string ( a[D] ) + ops[op3] + res; //检查是否有同样的表达式 if( !findString( results, res ) ) results.push_back( res ); else continue; cout << res << "= 24" << endl; } double r22 = cal( a[C], a[D], op2 ); // (C op2 D) || (D op2 C) double r32 = cal( r1, r22, op3 ); // (r1 op2 r22) || (r22 op2 r1) if( fabs( r32 - 24 ) < 10E-5 && ( r22 >= 0 ) ) { find = true; string temp; if( op1 < 5 ) res = "(" + num_string( a[A] ) + ops[op1] + num_string( a[B] ) + ")"; else res = "(" + num_string( a[B] ) + ops[op1] + num_string( a[A] ) + ")"; if( op2 < 5 ) temp = "(" + num_string( a[C] ) + ops[op2] + num_string( a[D] ) + ")"; else temp = "(" + num_string( a[D] ) + ops[op2] + num_string( a[C] ) + ")"; if( op3 < 5 ) res = res + ops[op3] + temp; else res = temp + ops[op3] + res; //检查是否有同样的表达式 if( !findString( results, res ) ) results.push_back( res ); else continue; cout << res << "= 24" << endl; } } } } } } if( !find ) { cout << "Sorry ,无法计算\n"; return false; } else return true; } int main() { vector<double> a( 4, 0 ); while( cin >> a[0] >> a[1] >> a[2] >> a[3] ) { is24( a ); } }
#include "Widget.h" #include <QtWidgets> QString ops[] = { "#","+","-","*","/","-","/" }; int num[] = { 0,1,7,5,10 }; int idx = 0; Widget::Widget(QWidget *parent) : QWidget(parent) { QPalette palette; palette.setColor(QPalette::Window,Qt::red); QHBoxLayout *labsLayout = new QHBoxLayout; for (int i = 0; i < 4; ++i) { labs[i] = new QLabel; labs[i]->setAutoFillBackground(true); labs[i]->setPalette(palette); labs[i]->setFrameStyle(QFrame::Panel ); labs[i]->setAlignment(Qt::AlignCenter); labs[i]->setMinimumHeight(50); labs[i]->setMargin(10); labsLayout->addWidget(labs[i]); } QGridLayout *btnsLayout = new QGridLayout; for (int i = 0; i < 10; ++i) { QPushButton *btn = new QPushButton(QString::number(i+1)); connect(btn,&QPushButton::clicked,[=](){ labs[idx]->setText(btn->text()); idx +=1; if(idx==1){ for (int i = 1; i < 4; ++i) { labs[i]->setText(""); } edit->clear(); } if(idx==4){ idx %= 4; get24(); } }); btnsLayout->addWidget(btn,i/5,i%5); } edit = new QTextEdit; edit->setReadOnly(true); QVBoxLayout *mainLayout = new QVBoxLayout(this); mainLayout->addLayout(labsLayout); mainLayout->addWidget(edit); mainLayout->addLayout(btnsLayout); } double Widget::cal(double x, double y, int op) { switch( op ) { case 1:return x + y; case 2:return x - y; case 3:return x * y; case 4: { if( y == 0 ) return -1000; return x / y; } case 5: return y - x; case 6: { if( x == 0 ) return -1000; return y / x; } default: return -1000; } } bool Widget::findString(QVector<QString> &vec, const QString &str) { for( const QString var : vec ) { if( var == str ) return true; } return false; } void Widget::get24() { num[1] = labs[0]->text().toInt(); num[2] = labs[1]->text().toInt(); num[3] = labs[2]->text().toInt(); num[4] = labs[3]->text().toInt(); QVector < QString > results; bool find = false; QString res; //可以考虑使用逆波兰表达式,脱去括号,求得最终的表达式,加入表达式集,去除相同的部分 for( int A = 1; A <= 4; A++ ) { for( int B = 1; B <= 4; B++ ) { if( B == A ) continue; for( int C = 1; C <= 4; C++ ) { if( C == A || C == B ) continue; for( int D = 1; D <= 4; D++ ) { if( D == A || D == B || D == C ) continue; for( int op1 = 1; op1 <= 4; op1++ ) for( int op2 = 1; op2 <= 6; op2++ ) for( int op3 = 1; op3 <= 6; op3++ ) { double r1 = cal( num[A], num[B], op1 ); // (A op1 B) || (B op1 A) if( r1 < 0 ) continue; double r21 = cal( r1, num[C], op2 ); // (r1 op2 C) || (C op2 r1) double r31 = cal( r21, num[D], op3 ); // (r21 op2 D) || (D op2 r21) // if( r31 == 24 && ( r21 >= 0 ) ) if( qAbs(r31 - 24)<10E-5 && ( r21 >= 0 ) ) { //cout << "r31\n"; find = true; if( op1 < 5 ) res = "(" + QString::number( num[A] ) + ops[op1] + QString::number( num[B] ) + ")"; else res = "(" + QString::number( num[B] ) + ops[op1] + QString::number( num[A] ) + ")"; if( op2 < 5 ) res = "(" + res + ops[op2] + QString::number( num[C] ) + ")"; else res = "(" + QString::number( num[C] ) + ops[op2] + res + ")"; if( op3 < 5 ) res = res + ops[op3] + QString::number( num[D] ); else res = QString::number( num[D] ) + ops[op3] + res; //检查是否有同样的表达式 if( !findString( results, res ) ) results.push_back( res ); else continue; // qDebug() << res << "= 24" ; edit->append(res+" = 24"); } double r22 = cal( num[C], num[D], op2 ); // (C op2 D) || (D op2 C) double r32 = cal( r1, r22, op3 ); // (r1 op2 r22) || (r22 op2 r1) if( qAbs(r32 - 24)<10E-5 && ( r22 >= 0 ) ) { find = true; QString temp; if( op1 < 5 ) res = "(" + QString::number( num[A] ) + ops[op1] + QString::number( num[B] ) + ")"; else res = "(" + QString::number( num[B] ) + ops[op1] + QString::number( num[A] ) + ")"; if( op2 < 5 ) temp = "(" + QString::number( num[C] ) + ops[op2] + QString::number( num[D] ) + ")"; else temp = "(" + QString::number( num[D] ) + ops[op2] + QString::number( num[C] ) + ")"; if( op3 < 5 ) res = res + ops[op3] + temp; else res = temp + ops[op3] + res; //检查是否有同样的表达式 if( !findString( results, res ) ) results.push_back( res ); else continue; // qDebug() << res << "= 24"; edit->append(res+" = 24"); } } } } } } if( !find ) edit->append("Sorry ,无法计算") ; else edit->moveCursor(QTextCursor::Start); }
有感兴趣的 可以直接下载 0 积分
https://download.csdn.net/download/hitzsf/85750810, 0积分下载
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。