请教一个关于分析彩票的问题

suncharlie 2005-12-10 09:53:15
则是这样的:从1到33之间任意取6个数字(不重复),然后输出满足如下条件的6个数字的序列:
这6个数字之间任意+,-(不能乘除)的结果可以等于一个事先设定的值
注意,这6个数字不一定全部参加运算,也可以部分运算,只要结果等于事先设定的值即可
另外,事先设定的值是一组,可能有好几个,而且值是在运行期间由用户输入的

不知道我说清楚没有

有个简单的方法:将可能的序列(包括运算符)都罗列出来,运算符有+,-,&三种,其中&表示运算到此为止,
如“4+6-7&8-14+22”就表示4+6-7,只有前面三个数字参加运算了。然后用中缀或者后缀表达式就可以求值了,再一个个比较

但是有如下的问题:
我初步测试了一下,运行时间可能非常长,估计有若干小时,而且期间cpu一直是100%。基数和可能的情况太大太多了

请问一下有没有更好的思路呢?谢谢
...全文
239 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
cunsh 2005-12-10
  • 打赏
  • 举报
回复
楼上.

"另外,事先设定的值是一组,可能有好几个,".................
RainWindy 2005-12-10
  • 打赏
  • 举报
回复
将你的题目更改为:
有36个数(1,2,3,...,33),从中取若干个数,但最多只能取6个数,取出来的数可能为-,也可能为+,将取出来的数加上符号后计算它的值,如果这个值等于一个设定的值,则这个取数是有效的。

我们分成6种情况:
1、只取一个数:33种情况
每个数有两种情况+或-共33*2=66
2、取二个数:528
528*2*2=2112
3、取三个数:5456
5456*2*2*2=43648
4、取四个数:40920
40920*2*2*2*2=654720
5、取五个数:237336
237336*2*2*2*2*2=7594752
6、取六个数:1107568
1107568*2*2*2*2*2*2=70884352

我们获取一种取数时可以这样处理:
比如我们取6个数,则每个数有两种情况,共64种情况,分别由6位代码,则对应位为0表示取-,对应位为1表示取+
比如00110110(0x36=54)表示1-2+3+4-5+6+
计算值就可以了。

而且可以根据你需要的值可以排队一些数据,
比如1-33可计算的值的范围是[-561,+561]
如果需要的值为100,则取两个数最大也只能是35+36=71,需要两个数不需要考虑。

cunsh 2005-12-10
  • 打赏
  • 举报
回复
看不懂楼主的题目的意思.这儿有个穷举的例子.楼主参考看有没有用了.
/*
* 题目如下:
*
* 使用加号'+',减号'-',和等号'=',插入到1234567890中,使其等式成立.
* 为简单起见,只求解等号在最右边的情况.如:
* 1-2+34+56-7+8=90 符合要求
* 12-3+4+5+6-7-8-9=0 符合要求
* 12+3-4+5-6+7-8=9+0 不符合要求
* 程序代码规范,结果正确,要有必要的注释.输出所有可能的情况。
* 使用TC2.0,TC3.0,VC6.0,dec++ 编译器均可.
*/

#include<iostream>
#include<strstream>
#include<string>
#include<algorithm>
using namespace std;

//数字部分
char a[] = "1234567890";

//符号部分 '+' '-' '=' ' '
char c[10] = " ";

//测试表达式中"="两边是不是相等,如果相等就打印表达式
void ceshi(){

//构造表达式,把9个符号嵌入10个数字之间.
char buf[32]={0};
for(int i=0; i<9; i++){
buf[2*i] = a[i];
buf[2*i+1] = c[i];
}
buf[18] = '0';

//去掉表达式中的空格
string s(buf);
string::iterator iter = remove(s.begin(),s.end(),' ');
s.erase(iter,s.end());

//构造输入流.
istrstream strbuf(s.c_str());


long sun = 0; // "="左边的各项之和
long n; //从strbuf流读出的各个数据项
while (1){
strbuf >> n;
if(!strbuf.good()) break;
sun += n;
}
strbuf.clear();
strbuf.ignore();
strbuf >> n;

if ( sun == n)
cout << s << endl;
}

//穷举由 +-=空格 组成的长度为9的符号的排列
void func(int x){
if (x >= 9) return;
c[x] = '+';
func(x + 1);
c[x] = '-';
func(x + 1);
c[x] = ' ';
func(x + 1);
c[x] = '=';
ceshi();
c[x] = ' ';
}

int main(){
func(0);
return 0;
}
northwolves 2005-12-10
  • 打赏
  • 举报
回复
如果象楼主的例子那样六个数只能由小到大,则有1076556096方案供选择,尚能接受。
northwolves 2005-12-10
  • 打赏
  • 举报
回复
你需要在(33*32*31*30*29*28)*3^4 * 2=129186731520 种排列方法里筛选结果为设定的值的排列
fiftymetre 2005-12-10
  • 打赏
  • 举报
回复
这道题目,不可能有效率非常高的算法的,只能在穷举身上做文章,比如什么样的情况不在穷举的范围之内..

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧