[从头学数学] 第40节 测量

剧情提要:
[机器小伟]在[工程师阿伟]的陪同下进入练气期第五层功法的修炼,
这次要修炼的目标是[测量]。

正剧开始:

星历2016年01月13日 09:39:56, 银河系厄尔斯星球中华帝国江南行省。
[工程师阿伟]正在和[机器小伟]一起研究测量的技术。


09:41:39, 小伟认识了毫米和分米。

[从头学数学] 第40节 测量_第1张图片


还有厘米

[从头学数学] 第40节 测量_第2张图片

小伟拿出了自己的尺子:


<span style="font-size:18px;">function myDraw() {  
    var config = new PlotConfiguration();  
    config.init();  
    config.setPreference(); 
	//config.setSector(1,1,1,1);
 
    //config.axis2D(0, 0, 180);  
	
	//图片
	var image = new Image();
	image.src = "./1.jpg";
	
	var ruler = new Ruler();
	
	image.onload = function() {
		plot.save()
			.scale(1.07, 1)
			.drawImage(image)
			.restore();

		ruler.ruler(10, 128, 280, 0);
	}
	
}</span>

[从头学数学] 第40节 测量_第3张图片


小伟看到了分米


[从头学数学] 第40节 测量_第4张图片

接着做了一次测量长度的练习:

[从头学数学] 第40节 测量_第5张图片

[从头学数学] 第40节 测量_第6张图片


[从头学数学] 第40节 测量_第7张图片

接着认识千米

[从头学数学] 第40节 测量_第8张图片



接着小伟看到了[人叫板老师]举的一个例子,让小伟选择路径,小伟兴奋起来了:

[从头学数学] 第40节 测量_第9张图片


来看看小伟从家到体育场有几种路线选择吧:

<span style="font-size:18px;">小伟家-->学校-->医院-->体育场
小伟家-->小年宫-->医院-->体育场
小伟家-->小年宫-->公园-->体育场
小伟家-->学校-->医院-->小年宫-->公园-->体育场</span>


小伟是怎么知道的呢?是这样的:

<span style="font-size:18px;">/**
* @usage   打印给定两个地点间所有路径
* @author  mw
* @date    2016年01月13日  星期三  09:50:23 
* @param
* @return
*
*/
function myDraw() {  
    var config = new PlotConfiguration();  
    config.init();  
    config.setPreference(); 
	//config.setSector(1,1,1,1);
 
    //config.axis2D(0, 0, 180);  
	
	/*
		求解以下问题:
		(1)有六个地点,编号1-6,地点之间的连通情况为边数组
	*/
	//顶点数量
	var vertexNum = 6;
	var edge = [[1,6],[1,2],[2,5],[2,3],[3,4],[4,5],[5,6]];
	var edges = edge.length;
	
	var pathMap = new Map();
	
	for (var i = 0; i < edges; i++) {
		pathMap.put(edge[i][0], edge[i][1]);
		pathMap.put(edge[i][1], edge[i][0]);

	}
	
	pathMap.sort();
	
	/*
		(2)现在要求给出两点(6,3),
		求出所有能从地点6到达地点3的选择
	*/
	var begin = 6;
	var end = 3;
	
	//可增长的路径
	var pathArray = new Array();
	//pathArray中的一个选择
	var choice = new Array();
	//choice前提下的下一步选择
	var newChoice = new Array();
	//有效路径
	var effectivePath = new Array();
	//临时变量
	var tmp = 0, len = 0, len1 = 0;
	var count = 0;
	
	//把起点压入栈
	pathArray.push([begin]);	

	while (pathArray.length > 0) {
		
		//每次从选择集合中取出第一个选择

		choice = pathArray.shift();
		len = choice.length;
		if (len >= vertexNum) 
			break;

		//选择的最后一个元素
		tmp = choice[len-1];
		newChoice = pathMap.get(tmp);
		//document.write(choice.join(',')+'------'+newChoice.join(',')+'<br/>');
		
		len1 = newChoice.length;

		
		for (var i = 0; i < len1; i++) {
			for (var j = 0; j < len; j++) {
				//元素重复了
				if (newChoice[i] == choice[j]) {
					break;
				}
				//无重复元素
				if (j >= len-1) {
					if (newChoice[i] == end) {
						effectivePath.push(choice.concat(newChoice[i]));
					}
					else {
						pathArray.push(choice.concat(newChoice[i]));
						//document.write(choice.concat(newChoice[i]).join(',')+'<br/>');
					}
				}
			}
		}
	}
	
	var addressString = ['学校', '医院', '体育场', '公园', '小年宫', '小伟家'];
	var s = ''; 
	len = effectivePath.length;
	
	
	for (var i = 0; i < len; i++) {
		s = '';
		choice = effectivePath[i];
		len1 = choice.length;
		for (var j = 0; j < len1; j++) {
			s +=addressString[choice[j]-1];
			if (j < len1-1) {
				s += '-->';
			}
		}
		document.write(s+'<br/>');
	}
	
}
</span>


既然有这么些路径可以选择,但是哪条最短呢?

先来看结果:

<span style="font-size:18px;">>>> 
选择的路线是:
小伟家-->小年宫-->公园-->体育场 ,这条路线总长为920米</span>


小伟是怎么知道的呢?是这样的:

<span style="font-size:18px;">###
# @usage   求两个给定地点,所有路径中的最短值
# @author  mw
# @date    2016年01月13日  星期三  09:50:23 
# @param
# @return
#
###
class DijkstraPath():
    #初始化
    def __init__(self, node_map):
        self.node_map = node_map;
        self.node_length = len(node_map);
        self.used_node_list = [];
        self.collected_node_dict = {};
        
    #调用函数
    def __call__(self, from_node, to_node):
        self.from_node = from_node;
        self.to_node = to_node;
        self._init_dijkstra();
        return self._format_path();
    
    def _init_dijkstra(self):
        self.used_node_list.append(self.from_node);
        self.collected_node_dict[self.from_node] = [0, -1];
        for index1, node1 in enumerate(self.node_map[self.from_node]):
            if node1:
                self.collected_node_dict[index1] = [node1, self.from_node];
        self._foreach_dijkstra();
        
    def _foreach_dijkstra(self):
        #保证每个点最多只到一次
        if len(self.used_node_list) == self.node_length - 1:
            return;
        #由于items()方法会改变原字典内容,所以此处拷贝副本
        collected_node_dict = dict(self.collected_node_dict);
        # 遍历已有权值节点
        for key, val in collected_node_dict.items():  
            if key not in self.used_node_list and key != to_node:
                self.used_node_list.append(key);
            else:
                continue;
            # 对节点进行遍历
            for index1, node1 in enumerate(self.node_map[key]):  
                # 如果节点在权值节点中并且权值大于新权值
                if node1 and index1 in self.collected_node_dict \
                   and self.collected_node_dict[index1][0] > node1 + val[0]:
                    # 更新权值
                    self.collected_node_dict[index1][0] = node1 + val[0]
                    self.collected_node_dict[index1][1] = key;
                elif node1 and index1 not in self.collected_node_dict:
                    self.collected_node_dict[index1] = [node1 + val[0], key];
        #递归
        self._foreach_dijkstra();
        
    def _format_path(self):
        node_list = [];
        temp_node = self.to_node;
        node_list.append((temp_node, self.collected_node_dict[temp_node][0]));
        while self.collected_node_dict[temp_node][1] != -1:
            temp_node = self.collected_node_dict[temp_node][1];
            node_list.append((temp_node, self.collected_node_dict[temp_node][0]));
        node_list.reverse();
        return node_list;

    def pathString(self, node):
        node_list = self._format_path();
        size = len(node_list);
        s = '选择的路线是:\n';
        for i in range(size):
            if i < size-1:
                s += str(node[node_list[i][0]])+'-->';
            else:
                s += str(node[node_list[i][0]]);
        s+= ' ,这条路线总长为{0}米'.format(node_list[size-1][1]);
        return s;
    
def set_node_map(node_map, node, node_list):
    for x, y, val in node_list:
        node_map[node.index(x)][node.index(y)] = node_map[node.index(y)][node.index(x)] =  val
        
if __name__ == "__main__":
    #节点表
    node = [1, 2, 3, 4, 5, 6];
    addressString = ['学校', '医院', '体育场', '公园', '小年宫', '小伟家'];
    #带权重的边表
    node_list = [(1,6,250), (1,2,300), (5,6,300), (4,5,470),
                 (3,4,150), (2,3,450),(2,5,250)];
    #节点数量的平方
    node_map = [[0 for val in range(len(node))] for val in range(len(node))];
    #预设节点表
    set_node_map(node_map, node, node_list);
    #Demo 求A --> D 的最短距离
    from_node = node.index(6);
    to_node = node.index(3);

    #求取路径
    dijkstrapath = DijkstraPath(node_map);
    #路径字符串
    path = dijkstrapath(from_node, to_node);

    print(dijkstrapath.pathString(addressString));
</span>


嗯嗯,小伟终于知道从自己家去哪要走哪条路了,不错。


[从头学数学] 第40节 测量_第10张图片



接着小伟认识了吨和千克:

[从头学数学] 第40节 测量_第11张图片

来做一做这个题吧:

<span style="font-size:18px;">>>> 
卡车一可以装600, 400, 800, , 另一辆卡车装1000, 700, 
卡车一可以装600, 1000, , 另一辆卡车装400, 800, 700, 
卡车一可以装800, 1000, , 另一辆卡车装600, 400, 700, 
卡车一可以装600, 400, 700, , 另一辆卡车装800, 1000, 
卡车一可以装400, 800, 700, , 另一辆卡车装600, 1000, 
卡车一可以装1000, 700, , 另一辆卡车装600, 400, 800, </span>

怎么得到这个结果的呢?是这样的:

<span style="font-size:18px;">def tmp():
    N = 5;
    array = [0]*N;
    weight = [600,400,800,1000,700];
    totalWeight = 0;
    firstTruck = 0;

    #所有货物的总重量
    for i in range(len(weight)):
        totalWeight+=weight[i];

    while (array[N-1] < 2):
        firstTruck = 0;
        for i in range(len(weight)):
            firstTruck += weight[i]*array[i];

        if firstTruck < 2000 and firstTruck > totalWeight-2000:
            s1 = '卡车一可以装';
            s2 = '另一辆卡车装';
            for i in range(len(weight)):
                if array[i] != 0:
                    s1 += str(weight[i])+', ';
                else:
                    s2 += str(weight[i])+', ';
            print(s1+', '+s2);

        
        array[0]+=1;
        for i in range(N-1):
            if array[i] > 1:
                array[i+1]+=1;
                array[i] = 0;
    return;</span>


这几位动物怎么过河呢,小伟给出了解答:

<span style="font-size:18px;">>>> 
第一批过河的:熊, 总共340千克,, 另一批过河的:山羊, 兔, 牛, 总共900千克,
第一批过河的:熊, 山羊, 总共580千克,, 另一批过河的:兔, 牛, 总共660千克,
第一批过河的:熊, 兔, 总共500千克,, 另一批过河的:山羊, 牛, 总共740千克,
第一批过河的:山羊, 兔, 总共400千克,, 另一批过河的:熊, 牛, 总共840千克,
第一批过河的:熊, 山羊, 兔, 总共740千克,, 另一批过河的:牛, 总共500千克,
第一批过河的:牛, 总共500千克,, 另一批过河的:熊, 山羊, 兔, 总共740千克,
第一批过河的:熊, 牛, 总共840千克,, 另一批过河的:山羊, 兔, 总共400千克,
第一批过河的:山羊, 牛, 总共740千克,, 另一批过河的:熊, 兔, 总共500千克,
第一批过河的:兔, 牛, 总共660千克,, 另一批过河的:熊, 山羊, 总共580千克,
第一批过河的:山羊, 兔, 牛, 总共900千克,, 另一批过河的:熊, 总共340千克,</span>

可以看出来他们的选择很多,这桥还是很结实的。


<span style="font-size:18px;">def tmp():
    N = 4;
    array = [0]*N;
    weight = [340,240,160, 500];
    name = ['熊', '山羊', '兔', '牛'];
    totalWeight = 0;
    firstTeam = 0;

    #所有过河者的总重量
    for i in range(len(weight)):
        totalWeight+=weight[i];

    while (array[N-1] < 2):
        firstTeam = 0;
        for i in range(len(weight)):
            firstTeam += weight[i]*array[i];

        if firstTeam < 1000 and firstTeam > totalWeight-1000:
            s1 = '第一批过河的:';
            s2 = '另一批过河的:';
            for i in range(len(weight)):
                if array[i] != 0:
                    s1 += str(name[i])+', ';
                else:
                    s2 += str(name[i])+', ';
            s1 += '总共'+str(firstTeam)+'千克,';
            s2 += '总共'+str(totalWeight-firstTeam)+'千克,';
            print(s1+', '+s2);

        
        array[0]+=1;
        for i in range(N-1):
            if array[i] > 1:
                array[i+1]+=1;
                array[i] = 0;
    return;</span>


学得差不多了,小伟该去玩一会了。

本节到此结束,欲知后事如何,请看下回分解。



你可能感兴趣的:([从头学数学] 第40节 测量)