称假币问题实验报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
称假币问题实验报告
——信息论第一次作业
学校:西安电子科技大学
班别:1307011班
姓名:***
学号:***********
一、问题重述
盒中有n个外形相同的硬币,知道其中有一个重量不同的硬币,但不知是比真币轻,还是比真币重。现用一无砝码天枰对现有硬币进行称重来鉴别假币,无砝码天枰的称重有3种结果,平衡,向左倾,向右倾。当n=12;n=39;n=n时,如何称重使实验次数最少,鉴别出假币并判断出轻或重?
二、问题分析
根据熵的可加性,一个复合事件的平均不确定性可以通过多次试验逐步解除。如果我们使实验所获得的信息量最大,那么所需要的总试验次数就最少。
(1)每一次使用天平,可以得到三种可能,左偏,右偏,平衡,而且这三种可能是概率相等的,所以每一次使用天平的结果都携带log3的信息量。
(2)要从N个硬币中找到那个不一样,可以有2N种概率相同的可能,每个硬币都可能偏轻或者偏重,这个事件所携带的信息量是log2N。
所以可以得到最少可以使用log2N/log3次天平就可以凑够信息量,指出哪一个是不一样的。
三、问题解决
【问题一】n=12
设12个硬币的编号分别为:1,2,3,4,5,6,7,8,9,10,11,12.三次称重安排如下表:
设3种称重结果分别表示为:0:平衡,1:左重,-1:右重。得到如下鉴别结果:
参见上面表格,可用矩阵表示3次称重的安排,矩阵上面标明12次硬币的序号,矩阵
的3行分别表示3次连续称重时硬币的放置状态,1表示放到左盘,-1表示放到右盘,0表示放到旁边(不参与称重)。
1234567891011121111-1-1-1-10
01000-11110-1-1-101-1011-10-11-10⎛⎫
⎪
⎪ ⎪⎝
⎭ 比较上面的表格和矩阵,发现:如果检测结果与上面矩阵的某列符合,则对应序号的硬币为
假币,且重量较重;如果检查结果与不包含在上述矩阵的列中,则1、-1互换,得到假币对应序号,但重量较轻。
【问题二】n=39
查阅资料得到,n 次称量最多可以在个球中找到不同的球,并判断它的轻重。 (1)编码:
知道了球数,就能算出需要称量几次;
以这个次数作为长度,使用0、1、2排列组合进行编码,如001021、212022等等,再去掉全0、全1和全2,可知一共有个编码;
如果在一个编码中,第一处相邻数字不同的情况是01、12或20,则我们称它为正序码,如1120021;
否则为逆序码,如2221012;
在长度为n 的编码中,正序码和逆序码的数量相等,均为个。 (2)赋值:
如果把一个正序码中的0换成1,1换成2,2换成0,则它仍然是正序码;
根据这个原理,我们把所有正序码按3个3个进行分组,如12001、20112、01220这3个就是一组;
把正序码一组一组地分配给小球,每球一个,直到分完;
然后把每个正序码的0换成2,2换成0,它就变成了一个逆序码,如12001变成10221; 这样,每个小球就有了两个编码,一个正序,一个逆序,而且所有球都不重复。 (3)称重:
第一轮,我们把所有正序码第一位为0的小球放在天平左侧,为2的小球放在右侧,其它的放在旁边;
如果天平左倾,记为0;右倾,记为2;平衡,记为1;
然后是第二轮,把第二位为0的小球放在左侧,为2的放在右侧,同样记下称量结果; 每一轮都按这个顺序进行,一共要称n 次,最终结果是个n 位的编码; 如果编码等于某个小球的正序码,则这个小球比其它球重; 如果编码等于某个小球的逆序码,则这个小球比其它球轻。
【问题三】n=n
方法与问题二同
四、算法演示
以n=12为例
(1)编号
(2)称重
正序码第一位为0的硬币放在天枰的左侧,第一位为2的放在右侧,第一位为1的放在旁边
结果与事先挑选的硬币一致
五、编写代码
#include
#include
#include
#include
#include
#include
using namespace std;
set
int k,num,n,m;
int vsi[10005],weight[10005],fflag,s2i[10005],heavy_or_light; char s[10005][1005],rcd[10005];
int p=1,integ,leicheng=1;
void ten2three(int a,char *s)
{
num=0;
for(int i=0;i s[i]='0'; while(1) { s[num++]=a%3+'0'; a/=3; if(a<=1) { s[num]=a+'0'; break; } } } int judge1(int a) { char sss[3][10005]; int integ[3]; ten2three(a,sss[0]); integ[0]=atoi(sss[0]); for(int i=0;i { if(sss[0][i]=='0') sss[1][i]='1'; else if(sss[0][i]=='1') sss[1][i]='2'; else if(sss[0][i]=='2') sss[1][i]='0'; } integ[1]=atoi(sss[1]); for(int i=0;i { if(sss[1][i]=='0') sss[2][i]='1'; else if(sss[1][i]=='1') sss[2][i]='2'; else if(sss[1][i]=='2') sss[2][i]='0'; } integ[2]=atoi(sss[2]); int ok=1; for(int i=0;i<=2;i++) if(vsi[integ[i]]) { ok=0; break; }