本帖最后由 夏影 于 2010年12月6日 12:46 编辑
正好在研究猜数字,于是我也顺便扔一下上来吧……
虽然代码风格有点乱,不过整体思路还是比较简单的。应该仔细读一读就能看懂……
这代码在学校讨论区里面讨论了一下,应该有更优化的策略,不过出于程序的简洁性考虑,还是算了。
为了“程序(或项目)不要求太大,可以是一个小算法、一个较实用的类或一个小的应用程序等,同学们要自己动手锻炼。”的要求……
编译环境codeblocks 10.05通过……
#include<iostream>
#include<cstdlib>
#include<time.h>
using namespace std;
int f(int c[],bool d[],int e[])//正确答案c,猜测答案e,返回一个2位数,10位值为A的数量,个位值为B的数量。参考猜数字规则……
{
int r=0;
for(int i=0; i<4; ++i)
{
r+=d[e];//如果这个数字存在,个位自增。
r+=(c==e)*9;//如果位数相符,10位自增。
}
return r;
}
int main()
{
srand((unsigned)time(NULL));
int c[4]= {},e[4],g[4],i,t,z,q(0);
bool d[10]= {},d2[10]= {},h[10][10][10][10]= {};//d与d2记录某个数字是否已经出现过,h存储已经被排除的数。
for(i=0; i<4; ++i)
{
do t=rand()%10;
while(d[t]);//不重复的数字…
c=t;
d[t]=true;//标记已经出现的数字
}//产生一个随机不重复的四位数
cout<<c[0]<<c[1]<<c[2]<<c[3]<<endl;//输出这个随机数
system(\"pause\");//等待
for(e[0]=0; e[0]<10; ++e[0])
for(e[1]=0; e[1]<10; ++e[1])
for(e[2]=0; e[2]<10; ++e[2])
for(e[3]=0; e[3]<10; ++e[3])//穷举四位数…
{
if (h[e[0]][e[1]][e[2]][e[3]]||e[0]==e[1]||e[0]==e[2]||e[0]==e[3]||e[1]==e[2]||e[1]==e[3]||e[2]==e[3])
continue;//如果这个数字已经被排除或者有两个数位上的数字相同的话跳过。
z=f(c,d,e);//猜数,Z的值为A与B的数量。
for (g[0]=0; g[0]<10; ++g[0])
for(g[1]=0; g[1]<10; ++g[1])
for(g[2]=0; g[2]<10; ++g[2])
for(g[3]=0; g[3]<10; ++g[3])//穷举,对剩下的所有数进行筛选。不符合规定的淘汰掉
{
if (h[g[0]][g[1]][g[2]][g[3]]||g[0]==g[1]||g[0]==g[2]||g[0]==g[3]||g[1]==g[2]||g[1]==g[3]||g[2]==g[3])
continue;//同上,如果这个数字已经被排除或者有两个数位上的数字相同的话跳过。
for(i=0; i<10; ++i)
d2=false;//初始化d2数组,其实可以用memset,我犯懒了。
for(i=0; i<4; ++i)
d2[g]=true;//标记
if (f(g,d2,e)!=z)//如果不符合猜测结果
h[g[0]][g[1]][g[2]][g[3]]=true;//灭了它。
}
cout<<e[0]<<e[1]<<e[2]<<e[3]<<' '<<z<<' '<<++q<<endl;//输出 猜测的数字,猜测的结果(一个2位数,10位值为A的数量,个位值为B的数量。参考猜数字规则……),猜测的次数。
}
return 0;
}
程序执行结果样例:
7158
请按任意键继续. . .
0123 10 1
0456 10 2
0789 2 3
7158 40 4
Process returned 0 (0x0) execution time : 0.265 s
Press any key to continue.
第一行是原始数字,后面是猜数字的过程,三个数依次是猜的数字,返回值(10位为A个位为B)和猜的次数。于是按照筛法,7158这个数只要猜到四次就能猜出来了…
下面这个就纯属蛋疼了……看看就好。
这个是修改后的,在外面加上一个生成0123-9876的原始数字的循环,对每一个数字进行都猜一遍,看看对于所有的数,最多需要多少步才能出解……#include<iostream>
#include<cstdlib>
#include<time.h>
#include<memory.h>
using namespace std;
int f(int c[],bool d[],int e[])
{
int r=0;
for(int i=0; i<4; ++i)
{
r+=d[e];
r+=(c==e)*9;
}
return r;
}
int main()
{
srand((unsigned)time(NULL));
int c[4]= {},e[4],g[4],i,z,m(0),q;
bool d[10]= {},d2[10]= {},h[10][10][10][10]= {};
for(c[0]=0; c[0]<10; ++c[0])for(c[1]=0; c[1]<10; ++c[1])for(c[2]=0; c[2]<10; ++c[2])for(c[3]=0; c[3]<10; ++c[3])
{
if (c[0]==c[1]||c[0]==c[2]||c[0]==c[3]||c[1]==c[2]||c[1]==c[3]||c[2]==c[3])continue;
for(i=0; i<10; ++i)d=false;
for(i=0; i<4; ++i)d[c]=true;
memset(h,0,sizeof( h ));
q=0;
for(e[0]=0; e[0]<10; ++e[0])for(e[1]=0; e[1]<10; ++e[1])for(e[2]=0; e[2]<10; ++e[2])for(e[3]=0; e[3]<10; ++e[3])
{
if (h[e[0]][e[1]][e[2]][e[3]]||e[0]==e[1]||e[0]==e[2]||e[0]==e[3]||e[1]==e[2]||e[1]==e[3]||e[2]==e[3])continue;
z=f(c,d,e);
for(g[0]=0; g[0]<10; ++g[0])for(g[1]=0; g[1]<10; ++g[1])for(g[2]=0; g[2]<10; ++g[2])for(g[3]=0; g[3]<10; ++g[3])
{
if (h[g[0]][g[1]][g[2]][g[3]]||g[0]==g[1]||g[0]==g[2]||g[0]==g[3]||g[1]==g[2]||g[1]==g[3]||g[2]==g[3])continue;
for(i=0; i<10; ++i)d2=false;
for(i=0; i<4; ++i)d2[g]=true;
if (f(g,d2,e)!=z)
{
h[g[0]][g[1]][g[2]][g[3]]=true;
}
}
q++;
}
cout<<c[0]<<c[1]<<c[2]<<c[3]<<' '<<q<<endl;
m=max(m,q);
}
cout<<m;
return 0;
}
程序执行结果如下:
0123 1
0124 2
0125 3
0126 4
0127 5
0128 6
0129 7
0132 2
0134 2
0135 3
......(中间省略)
9861 6
9862 7
9863 8
9864 5
9865 6
9867 5
9870 7
9871 7
9872 6
9873 5
9874 6
9875 6
9876 6
9
前面每一行依次是生成的原始数字和需要猜测的次数,最后一行输出的9是所有数据中最多需要猜测的次数。
于是蛋疼结论得出,对于任意4位数字,都可以9次内出解……