砝码分盐问题——从数学和计算机的角度分析(6)

本文从数学和计算机的角度深入探讨了砝码分盐问题,提出了一种直接计算所有正确解的方法。通过第3次称量过程的直接计算,避免了繁琐的分解过程,简化了算法。附带的代码实现展示了这一方法的有效性,能够输出所有正确的盐分解过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本博客(http://blog.youkuaiyun.com/livelylittlefish )贴出作者(阿波)相关研究、学习内容所做的笔记,欢迎广大朋友指正!

Content

0. 问题

1. 一些方法

2. 从数学的角度分析

3. 能否编程计算?

4. 一个改进的方法

5. 再改进的方法

6. 能否直接计算求出所有正确解?

6.1基本思想

6.2 3次称量过程

6.3如何创建节点?

6.4结果

6.5讨论

7. 一个更为简单的方法

8. 所有代码的自动编译、运行

9. 问题扩展

10. 体会

11. 总结

Reference

附录 1 :数学分解的代码weight1.c

附录 2 :数学分解程序weight1 的运行结果

附录 3 :树结构分解的代码weight2.c

附录 4 :再改进的方法的代码weight3.1.c/3.2.c/3.3.c

附录 5 :再改进的方法的代码weight3.1.c/3.2.c/3.3.c 的输出结果

附录 6 :直接计算正确分解的代码weight4.c

附录 7 :一个更简单的方法的代码weight5.1.c/5.2.c/5.3.c

              

6. 能否直接计算求出所有正确解?

 

34节的讨论,均是从这个角度出发:即找到所有有结果的分解并在所有结果中判断哪些分解过程是满足目标的分解。

5的讨论,从对第3次称量结果直接进行判断其是否满足目标这个角度出发。

能否再转换一下思路?——能否直接计算求出所有正确的解?

The answer is yes!

 

6.1 基本思想

 

2次分解(称量)后,直接将满足目标的第3次称量解求出,判断这个计算出来的第3次称量所用的砝码是否在砝码组合内。如果在,表明该次称量过程为所求的正确解;否则,放弃,继续判断。如下图。

 

 

——听起来,这个方法要简单地多。

 

6.2 3次称量过程

 

根据该基本思想,改写5的程序,第12次称量过程与5基本相同,不再列出,此处描述第3次称量过程。

3次称量过程统一为以下过程。

(1) 1次称量:z=x+y, x<=y

(2) 2次称量:x=x1+x2, x1<=x2

(3) 3次称量:对x1(x2)直接计算满足目标的x11x12(x21x22),下面重点描述。

若对x1称量,假设被分解为x1=x11+x12(这里x11x12的大小不定),则最后的分解结果为(x11,x12,x2,y),则直接计算出满足目标的x11=heap1-x2,根据x11计算x12=x1-x11,由此得出w=x11-x12x12-x11,然后在ws数组中查找w是否是已知的砝码,若是,则该分解即为所求的正确分解;否则,继续。代码如下。

00136: /** the 3rd weight, in this function, divide x1 and x2
00137:    unify them into the following equations
00138:    z = x + y, x <= y
00139:    x = x1 + x2, x1 <= x2
00140:    x1 = x11 + x12, x11 <= x12
00141:    that is, the salts divided: x11, x12, x2, y, then x11+x2=heap1 or x12+x2=heap
00142:    the basic thoughts: get x11(or x12)=heap1- x2, then, get x12(or x11)=x1- x11(or x12)
00143:    then, get w=x12- x11, find w in ws, if found, it is a correct division; otherwise, not a
00144:    correct division, do next.
00145: */
00146: int weight3(int x1, int x2, int curpos1, int child1, int step, struct Division_Node* node1)
00147: {
00148:    int k = 0, w = 0;
00149:    int curpos2 = curpos1;
00150:    int child2 = 0;
00151:    struct Division_Node *node2 = NULL;
00152:
00153:    //divide x1
00154:    {
00155:       int x11 = heap1 - x2;
00156:       int x12 = x1 - x11;
00157:       if (x11 <= x12)
00158:          w = x12 - x11;
00159:       else
00160:          w = x11 - x12;
00161:
00162:       for (k = 0; k < Max_Num; k++)
00163:       {
00164:          if (ws[k] == w)
00165:          {
00166:             node2 = create_node(node1, node2, curpos1, curpos2, step,
00167:                x1, x2, x11, x12, child1, child2);
00168:             child2++;
00169:             break;
00170:          }
00171:       }
00172:    }
00173:
00174:    //divide x2
00175:    if (x2 != x1) //to avoid repeatance
00176:    {
00177:       int x21 = heap1 - x1;
00178:       int x22 = x2 - x21;
00179:       if (x21 <= x22)
00180:          w = x22 - x21;
00181:       else
00182:          w = x21 - x22;
00183:
00184:       curpos2 = step;
00185:       for (k = 0; k < Max_Num; k++)
00186:       {
00187:          if (ws[k] == w)
00188:          {
00189:             node2 = create_node(node1, node2, curpos1, curpos2, step,
00190:                x1, x2, x21, x22, child1, child2);
00191:             child2++;
00192:             break;
00193:          }
00194:       }
00195:    }
00196:
00197:    if (node2)
00198:    node2->child_ = child2;
00199:
00200:    return child2;
00201: }


6.3 如何创建节点?

5.4。此处省略,具体代码请参考附录6

 

6.4 结果

5.5,输出结果为所有正确的分解过程。

 

6.5 讨论

该方法直接计算满足目标的第3次分解,好理解,也进一步简化了分解过程。

 

附录6:直接计算正确分解的代码weight4.c

上一节 下一节

, ,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值