n个数进行加减乘除得到m 小于四个的数还可以用穷举法,还是比较简单。n比较大的时候就行不通了,这个时候我考虑到了用递归的方法。就是从这n个数中取两个进行加减乘除,把得到的四种结果再分别和从剩余的n-2个数中的一个数再进行加减乘除。如此递归下去,直到这n个数全部进行过计算,最后看得到的结果是否等于m。我试着写了些代码,可是错得一塌糊涂。求正确的代码(c语言)。 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 是要用到全排列。范围嘛,n<=10,每个数小于等于15吧! 先 化简 4则运算和位置 等同情况 a+b+c-d 和 a-d+c+b 类似。 最好先整理出一个所为"算法结构",这样你再用DELPHI代码实现即可 化简四则运算貌似行不通吧。DELPHI没有学过 。 三个数a,b,c进行全排列:a,b,c;a,c,b;b,a,c;b,c,a;c,a,b;c,b,a;对每种排列结果最后两个数进行四则运算,如:a,b,c;p[0]=b + c; result[0][0]=a + p[0]; result[0][1]=a-p[0];result[0][2]=a*p[0];result[0][3]=a/p[0];p[1]=b - c; result[1][0]=a + p[1]; result[1][1]=a-p[1];result[1][2]=a*p[1];result[1][3]=a/p[1];p[2]=b * c; result[2][0]=a + p[2]; result[2][1]=a-p[2];result[2][2]=a*p[2];result[2][3]=a/p[2];p[3]=b / c; result[3][0]=a + p[3]; result[3][1]=a-p[3];result[3][2]=a*p[3];result[3][3]=a/p[3];看result中有没有一个值等于m的,如果有返回yes,没有返回no。 和delphi 没关系。。a-b-c 和a -(b+c) 结果是一样的这些是需要 做剪枝的。。 能提高一些效率。象这个问题 目标解空间一定的 主要是 搜索的时候 效率优化。 "先枚举某几种形式的算式"选择有效的方式缩小范围。。http://topic.csdn.net/t/20020128/09/503163.html to vividw:他们的思想我是基本理解了,可是他们的算法不能达到100%的精确。我这需要十分精确,耗费比较的时间和内存也是无所谓的。 不要求显示这n个数得到m的算术表达式,只要求判断能否得到m。 明白了,其实我是想倒推,如(a+b)+? = m? = m - a - b检索一下除a,b外是否有这个?,如果有就yes,没有继续其他其他运算规则一样,唯独带有除法的时候,所以要问清楚了 #include<iostream>#include<fstream>#include<sstream>#include<vector>#include<ctime>#include<cmath>using std::cout;using std::string;using std::vector;using std::ofstream;using std::stringstream;class Calc { public: Calc(){}; void print_result() const; bool run(const int src[], size_t sz, double n = 24.0, bool expr_calc = true, bool show = true); const string& get_expr() const { return expr;} size_t get_count_expr() const { return count_expr;} size_t get_count_func() const { return count_func;} private: Calc(const Calc&); Calc& operator=(const Calc&); bool init(const int src[], size_t sz, double n); bool calc(size_t step); inline bool calc2(size_t step, size_t pos2,double na, double nb, int op); void calc_expr(); void add_parentheses(string& str) { string tmp; tmp.reserve(str.size() + 2); tmp += '('; tmp += str; tmp += ')'; str.swap(tmp); } char get_op_char(int op) { return char(op >> RSHIFT); } int get_opv(int op) { return op & OPV_MASK; } //0-2位表示操作符的优先级 加减: 1 乘除2 初始值4 //+3位,即RFLAG标志,表示对减除法,交换两个操作数后再计算 //4-7位表示操作符,8-15位表示该操作符的ascii值 enum { OP_NULL = 4, RFLAG = 8, RSHIFT = 8, OPV_MASK = 7, FLAG_ADD = 0x10, FLAG_SUB = 0x20, FLAG_MUL = 0x40, FLAG_DIV = 0x80, ADD = '+' << RSHIFT | FLAG_ADD | 1, SUB = '-' << RSHIFT | FLAG_SUB | 1, MUL = '*' << RSHIFT | FLAG_MUL | 2, DIV = '/' << RSHIFT | FLAG_DIV | 2, RSUB = SUB | RFLAG, RDIV = DIV | RFLAG, }; struct Info_step { //记录每一步取两个数所进行的计算 size_t first; //第一个操作数位置 size_t second; //第二个操作数位置 int op; //操作符 }; size_t size; string expr; //得到的表达式 double result; //要得到的结果值 size_t count_expr; //处理的表达式总数 size_t count_func; //函数被调用次数 vector<int> old_number; //要计算的数 vector<double> number; //中间计算结果 vector<int> ops; //上一次计算所用的操作符,初始值要设为OP_NULL vector<Info_step> info_step;};bool Calc::init(const int src[], size_t sz, double n){ if (sz == 0 || src == NULL) return false; size = sz; expr.clear(); result = n; count_expr = 0; count_func = 0; old_number.assign(src, src + sz); number.assign(src, src+sz); ops.assign(sz, OP_NULL); info_step.clear(); info_step.resize(sz); return true;}bool Calc::run(const int src[], size_t sz, double n, bool expr_calc, bool show){ if (! init(src, sz, n)) return false; bool ret = calc(sz); if (ret && expr_calc) calc_expr(); if (show) print_result(); return ret;}void Calc::calc_expr(){ const size_t sz = size; static vector<string> str; static vector<int> op_prev; static stringstream ss; str.resize(sz); op_prev.assign(sz,OP_NULL); //初始值 for (size_t i = 0; i < sz; ++i) { ss << old_number[i]; getline(ss, str[i]); ss.clear(); } for (size_t k = sz; k-- > 1; ) { size_t i = info_step[k].first; size_t j = info_step[k].second; int op = info_step[k].op; int opv= get_opv(op); int op1v, op2v; if (op & RFLAG) { str[i].swap(str[j]); op1v = get_opv(op_prev[j]); op2v = get_opv(op_prev[i]); } else { op1v = get_opv(op_prev[i]); op2v = get_opv(op_prev[j]); } if (opv > op1v) add_parentheses(str[i]); if (opv > op2v || (opv == op2v && (op & (FLAG_SUB | FLAG_DIV)))) add_parentheses(str[j]); op_prev[i] = op; op_prev[j] = op_prev[k]; str[i].reserve(str[i].size() + str[j].size() + 1); str[i] += get_op_char(op); str[i] += str[j]; str[j].swap(str[k]); } expr.swap(str[0]);}bool Calc::calc(size_t step){ ++count_func; if (step <= 1) { ++count_expr; const double zero = 1e-9; if (fabs(result - number[0]) < zero) return true; return false; } --step; for (size_t i = 0; i < step; i++){ info_step[step].first = i; for(size_t j = i + 1; j <= step; j++) { info_step[step].second = j; double na = number[i]; double nb = number[j]; int op1 = ops[i]; int op2 = ops[j]; number[j] = number[step]; ops[j] = ops[step]; int tt = op1 | op2; bool ba = true, bb = true; if (tt & FLAG_SUB) ba = false; if (tt & FLAG_DIV) bb = false; if (ba) { if (calc2(step, i, na, nb, ADD)) return true; if (nb != 0 && calc2(step, i, na, nb, SUB)) return true; if (na != nb && na != 0 && calc2(step, i, na, nb, RSUB)) return true; } if (bb) { double nmul = na * nb; if (calc2(step, i, na, nb, MUL)) return true; if (na != 0 && nb !=0) { double ndiv = na / nb; if (nmul != ndiv && calc2(step,i,na, nb, DIV)) return true; double nrdiv = nb / na; if (nrdiv != ndiv && nrdiv != nmul && calc2(step,i,na, nb, RDIV)) return true; } } number[i] = na; number[j] = nb; ops[i] = op1; ops[j] = op2; } } return false;}inline bool Calc::calc2(size_t step, size_t pos2,double na,double nb, int op){ info_step[step].op = op; ops[pos2] = op; switch (op) { case ADD: number[pos2] = na + nb; break; case SUB: number[pos2] = na - nb; break; case MUL: number[pos2] = na * nb; break; case DIV: number[pos2] = na / nb; break; case RSUB: number[pos2] = nb - na; break; case RDIV: number[pos2] = nb / na; break; default : break; } return calc(step);}void Calc::print_result() const{ if (old_number.empty()) return; cout << "number: "; for (size_t i = 0; i < old_number.size(); ++i) cout << old_number[i] << " "; cout << "\n"; if (! expr.empty()) std::cout << "result: YES\n"; if(expr.empty())std::cout<<"result:NO\n";}int main(){ Calc calc; int i,N,r[100]; scanf("%d",&N); for(i=0;i<N;++i) { scanf("%d",&r[i]); } calc.run(r,N);}我从网上找了个c++版的,略作修改过。运行正确着。可我还没学c++,谁能帮我改成c语言版的。 F1调用帮助文件的问题 fastreport问题:怎样控制预览中得打印按钮只能打印一次或者点击 确定后,不出现预览直接打印,急?多谢? 怎么实现程序象windows服务一样运行,并且还在任务管理器中关闭不了 窗体问题 汉字转化成拼音 异构环境的数据库性能调优 一个旧的DELPHI问题 如何将已知的图形文件temp.bmp文件存入当前数据库(paradox)中的G字段中呢? 请问哪里有D6的书,我想看一看,多谢多谢 有需要Delphi 5开发人员指南的吗? Delphi 动态生成TreeView 求助Delphi 图片导入Excel
这样你再用DELPHI代码实现即可
a,b,c;
a,c,b;
b,a,c;
b,c,a;
c,a,b;
c,b,a;
对每种排列结果最后两个数进行四则运算,如:a,b,c;
p[0]=b + c; result[0][0]=a + p[0]; result[0][1]=a-p[0];result[0][2]=a*p[0];result[0][3]=a/p[0];
p[1]=b - c; result[1][0]=a + p[1]; result[1][1]=a-p[1];result[1][2]=a*p[1];result[1][3]=a/p[1];
p[2]=b * c; result[2][0]=a + p[2]; result[2][1]=a-p[2];result[2][2]=a*p[2];result[2][3]=a/p[2];
p[3]=b / c; result[3][0]=a + p[3]; result[3][1]=a-p[3];result[3][2]=a*p[3];result[3][3]=a/p[3];
看result中有没有一个值等于m的,如果有返回yes,没有返回no。
a-b-c
和a -(b+c) 结果是一样的
这些是需要 做剪枝的。。 能提高一些效率。象这个问题 目标解空间一定的 主要是 搜索的时候 效率优化
。
选择有效的方式缩小范围。。
http://topic.csdn.net/t/20020128/09/503163.html
(a+b)+? = m
? = m - a - b
检索一下除a,b外是否有这个?,如果有就yes,没有继续其他
其他运算规则一样,唯独带有除法的时候,所以要问清楚了
#include<fstream>
#include<sstream>
#include<vector>
#include<ctime>
#include<cmath>using std::cout;
using std::string;
using std::vector;
using std::ofstream;
using std::stringstream;class Calc {
public:
Calc(){};
void print_result() const;
bool run(const int src[], size_t sz, double n = 24.0,
bool expr_calc = true, bool show = true);
const string& get_expr() const { return expr;}
size_t get_count_expr() const { return count_expr;}
size_t get_count_func() const { return count_func;} private:
Calc(const Calc&);
Calc& operator=(const Calc&);
bool init(const int src[], size_t sz, double n);
bool calc(size_t step);
inline bool calc2(size_t step, size_t pos2,double na, double nb, int op);
void calc_expr(); void add_parentheses(string& str) {
string tmp; tmp.reserve(str.size() + 2);
tmp += '('; tmp += str; tmp += ')';
str.swap(tmp);
} char get_op_char(int op) { return char(op >> RSHIFT); }
int get_opv(int op) { return op & OPV_MASK; } //0-2位表示操作符的优先级 加减: 1 乘除2 初始值4
//+3位,即RFLAG标志,表示对减除法,交换两个操作数后再计算
//4-7位表示操作符,8-15位表示该操作符的ascii值
enum {
OP_NULL = 4, RFLAG = 8, RSHIFT = 8, OPV_MASK = 7,
FLAG_ADD = 0x10, FLAG_SUB = 0x20, FLAG_MUL = 0x40, FLAG_DIV = 0x80,
ADD = '+' << RSHIFT | FLAG_ADD | 1, SUB = '-' << RSHIFT | FLAG_SUB | 1,
MUL = '*' << RSHIFT | FLAG_MUL | 2, DIV = '/' << RSHIFT | FLAG_DIV | 2,
RSUB = SUB | RFLAG, RDIV = DIV | RFLAG,
}; struct Info_step { //记录每一步取两个数所进行的计算
size_t first; //第一个操作数位置
size_t second; //第二个操作数位置
int op; //操作符
}; size_t size;
string expr; //得到的表达式 double result; //要得到的结果值
size_t count_expr; //处理的表达式总数
size_t count_func; //函数被调用次数
vector<int> old_number; //要计算的数
vector<double> number; //中间计算结果
vector<int> ops; //上一次计算所用的操作符,初始值要设为OP_NULL
vector<Info_step> info_step;
};bool Calc::init(const int src[], size_t sz, double n)
{
if (sz == 0 || src == NULL) return false;
size = sz;
expr.clear();
result = n;
count_expr = 0;
count_func = 0;
old_number.assign(src, src + sz);
number.assign(src, src+sz);
ops.assign(sz, OP_NULL);
info_step.clear();
info_step.resize(sz);
return true;
}bool Calc::run(const int src[], size_t sz, double n, bool expr_calc, bool show)
{
if (! init(src, sz, n)) return false;
bool ret = calc(sz);
if (ret && expr_calc) calc_expr();
if (show) print_result();
return ret;
}
void Calc::calc_expr()
{
const size_t sz = size;
static vector<string> str;
static vector<int> op_prev;
static stringstream ss;
str.resize(sz);
op_prev.assign(sz,OP_NULL); //初始值
for (size_t i = 0; i < sz; ++i) {
ss << old_number[i];
getline(ss, str[i]);
ss.clear();
}
for (size_t k = sz; k-- > 1; ) {
size_t i = info_step[k].first;
size_t j = info_step[k].second;
int op = info_step[k].op;
int opv= get_opv(op);
int op1v, op2v;
if (op & RFLAG) {
str[i].swap(str[j]);
op1v = get_opv(op_prev[j]);
op2v = get_opv(op_prev[i]);
} else {
op1v = get_opv(op_prev[i]);
op2v = get_opv(op_prev[j]);
} if (opv > op1v) add_parentheses(str[i]);
if (opv > op2v || (opv == op2v && (op & (FLAG_SUB | FLAG_DIV))))
add_parentheses(str[j]);
op_prev[i] = op;
op_prev[j] = op_prev[k];
str[i].reserve(str[i].size() + str[j].size() + 1);
str[i] += get_op_char(op);
str[i] += str[j];
str[j].swap(str[k]);
}
expr.swap(str[0]);
}bool Calc::calc(size_t step)
{
++count_func;
if (step <= 1) {
++count_expr;
const double zero = 1e-9;
if (fabs(result - number[0]) < zero) return true;
return false;
}
--step;
for (size_t i = 0; i < step; i++){
info_step[step].first = i;
for(size_t j = i + 1; j <= step; j++) {
info_step[step].second = j;
double na = number[i];
double nb = number[j];
int op1 = ops[i];
int op2 = ops[j];
number[j] = number[step];
ops[j] = ops[step];
int tt = op1 | op2;
bool ba = true, bb = true;
if (tt & FLAG_SUB) ba = false;
if (tt & FLAG_DIV) bb = false; if (ba) {
if (calc2(step, i, na, nb, ADD)) return true;
if (nb != 0 && calc2(step, i, na, nb, SUB)) return true;
if (na != nb && na != 0 && calc2(step, i, na, nb, RSUB)) return true;
} if (bb) {
double nmul = na * nb;
if (calc2(step, i, na, nb, MUL)) return true;
if (na != 0 && nb !=0) {
double ndiv = na / nb;
if (nmul != ndiv && calc2(step,i,na, nb, DIV)) return true;
double nrdiv = nb / na;
if (nrdiv != ndiv && nrdiv != nmul && calc2(step,i,na, nb, RDIV))
return true;
}
}
number[i] = na;
number[j] = nb;
ops[i] = op1;
ops[j] = op2;
}
}
return false;
}inline bool Calc::calc2(size_t step, size_t pos2,double na,double nb, int op)
{
info_step[step].op = op;
ops[pos2] = op;
switch (op) {
case ADD: number[pos2] = na + nb; break;
case SUB: number[pos2] = na - nb; break;
case MUL: number[pos2] = na * nb; break;
case DIV: number[pos2] = na / nb; break;
case RSUB: number[pos2] = nb - na; break;
case RDIV: number[pos2] = nb / na; break;
default : break;
}
return calc(step);
}void Calc::print_result() const
{
if (old_number.empty()) return;
cout << "number: ";
for (size_t i = 0; i < old_number.size(); ++i)
cout << old_number[i] << " ";
cout << "\n";
if (! expr.empty()) std::cout << "result: YES\n";
if(expr.empty())std::cout<<"result:NO\n";
}int main()
{
Calc calc;
int i,N,r[100];
scanf("%d",&N);
for(i=0;i<N;++i)
{
scanf("%d",&r[i]);
}
calc.run(r,N);
}我从网上找了个c++版的,略作修改过。运行正确着。可我还没学c++,谁能帮我改成c语言版的。