探索数字迷塔问题及遇到指针无法访问内存的错误

Problem : 探索数字迷塔

Time Limit: 1 Sec  Memory Limit: 64 MB

Description

晶晶最近迷上了数字迷宫游戏,整天沉浸在一串串看似简单的数字中自得其乐。数字迷宫游戏的魅力体现在变化中隐含着不变的规律,归纳是探究数字迷宫的法宝之一。图10.1-1就是一个由线连接起来的数字小方格组成的数字迷塔。

这个迷塔共n层,它由n×(n+1)/2个小方格组成。每个小方格中都有一个数字,并且连着下一层的两个小方格。现从塔顶走到塔底,每一步只能走到相邻的方格中,则经过方格的数字之和最大值是多少?这个问题晶晶已经琢磨一天了,她感觉异常棘手。你能帮帮她吗?

Input

输入数据共n+1行,第1行是一个整数n(1≤n≤1000),表示数字迷塔的高度,接下来用n行数字表示数字迷塔,其中第i行有i个正整数,且所有的正整数均不大于100。

Output

输出可能得到的最大和。

Sample Input

5

9

12 15

10 6 8

2 18 9 5

19 7 10 4 16

Sample Output

59

HINT

样例说明:9→12→10→18→10

方法策略

  对于这个问题,首先我想到的是从特殊到一般的方法,即先考虑一个较少的输入范围,如输入高度为5,然后思考如何用实际方法解决这个问题,再得出一般性的结论。先来分析这个特殊的树,它是有向的图,每个节点(除叶子外)都有两个子节点,而且相邻两个节点还共有一个子节点。很容易把它想象一个楼梯的模型,那么父节点与子结点的位置关系就很清楚了,即子节点在父节点的正下方和右下角,所以遍历这棵树和建立树的结构就迎刃而解了。对于求最大消耗路径问题,考虑到父子节点间的关系,可以采用用动态规划的方法解决,即:

cost(总)= cost(父) +  MAX(cost(子左),cost(子右))

找到了递推关系,应该很容易计算出结果了。

  具体如何建立这棵树呢?首先,还是用老办法,定义一个结构来表示每个节点(含数据,左、右指针等成员)。然后考虑如何输入数据和初始化所有节点:首先定义一个方法,输入是树的高度,输出是根节点的地址(便于访问树);利用树的高度信息及确定每层所含节点的数目,所以可以直接用动态数组来生成每层的节点,但是同时还要保留该数组的首地址,便于下面访问节点,所以需要创建一个二级指针来记录; 最后用两层循环来让父结点的指针指向子节点即可。

 

相应代码:

 1 /*
 2  *  numberati.cpp
 3  *  Copyright 2015 Kevin <[email protected]_WINDOWS8>
 4  *
 5  *  This program is intented to solve the Digit Magic Tower problem.
 6  *
 7  */
 8
 9 #include<iostream>
10 using namespace std;
11
12 /* Definiton of Node with the struct type*/
13 struct Node{
14     int data;
15     Node * left;
16     Node * right;
17 };
18
19 /* Function Declaration */
20 Node * buildTree();
21 int findMaxPath(Node * root);
22 int max(int, int);
23
24 /* Drive for */
25 int main(){
26     Node * root = buildTree();
27     cout << findMaxPath(root);
28     return 0;
29 }
30
31 /* Utility function to build a tree */
32 Node * buildTree(){
33     int height=1;
34     cin >> height;
35
36     // Make space to hold the value
37     Node ** temp=new Node *[height];
38     for (int i = 0; i < height; i++){
39         temp[i] = new Node[i + 1];         // for every column, use a pointer to access the elements
40         for (int j = 0; j <= i; j++){
41             cin >> temp[i][j].data;
42             temp[i][j].left = NULL;
43             temp[i][j].right = NULL;        // Intilize the pointers
44         }
45     }
46
47     // To link the elements, make pointers point their children
48     for (int i = 0; i<height-1; i++){
49         for (int j = 0; j <= i; j++){
50             temp[i][j].left = &temp[i + 1][j];
51             temp[i][j].right = &temp[i + 1][j + 1];
52         }
53     }
54
55     return temp[0];                        // return the root node‘s adress
56 }
57
58 /* Utility function to find the max path, and return the final cost */
59 int findMaxPath(Node * root){
60     if (root==NULL)               // Intilize the pointer before using it.
61         return 0;
62
63     int Max = max(findMaxPath(root->left), findMaxPath(root->right));
64     return (root->data + Max);
65 }
66
67 /* Get the larger value from two inputs */
68 int max(int a, int b){
69     if (a<b)
70         return b;
71     else
72         return a;
73 }

编写代码中出现的问题:

  由于之前很久没有用c++,就把c++中一些基本而重要的概念忘记了。例如,在创建一个变量的时候,一定要适当地将它初始化,否则很容易出现运行时错误。特别是指针,由于它直接访问内存,若没有很好的处理,很容易就早成程序意外地终止。在编写这个程序中,我就不幸遇到这个问题,由于没有初始化节点的左右指针,出现了无法读取内存的运行时错误,导致自己调试了很久都没明白错误的来源(ps,也可能自己水平还不够吧)。因为个人觉得这个教训比较重要,在此记录该错误,希望以后能引以为鉴。

用VS2013调试:

注释掉初始化子节点的左右指针:

测试代码:

程序能启动运行

输入数据后运行中断:

调试代码发现:

当访问到叶子节点的指针时出现了错误,data=???,left=???,right=???

最后,去掉注释后,在dos窗口下用g++编译能正常运行:

时间: 2024-10-08 15:15:14

探索数字迷塔问题及遇到指针无法访问内存的错误的相关文章

Qt 代码: 子窗口调用父窗口(其实就是用指针直接访问)

之前的 Qt 编程大多只涉及简单的多窗口,并未染指窗口间的传值交互,想来还是“涉世未深”,对 Qt 的理解.应用还需殷勤努力. 这次的问题是这样的,我想要实现一个类似QQ.阿里旺旺的聊天客户端,在弹出表情对话框后,能够选择表情并返回给聊天窗口的消息输入框,这就需要两个窗口之间的传值交互. 首先想到的解决方法自然是使用Qt自带的signal/slot机制.即首先发信号给父窗口,父窗口接到信号执行槽函数发送一个携带所需数据的信号给子窗口.但是疑问来了:要在子窗口中接收到父窗口的信号必须进行signa

多文档中建立一个对话框类,通过这个方法来在其他类中得到对话框对象指针,访问对话框成员

{ // 添加内容 m_pDrawTool = new CDrawToolDlg; m_pDrawTool->Create(IDD_DRAWTOOLS, this); m_pDrawTool->ShowWindow(SW_SHOW); // 让窗口出现在屏幕右下方 CRect dlgRect; CRect mainRect; m_pDrawTool->GetClientRect(&dlgRect); GetWindowRect(mainRect); // 计算显示的坐标 int

指针指向一块内存,它的内容是所指内存的地址;而引用则是某块内存的别名(转)

1.指针与引用的区别: 指针是一块内存的地址值,而引用是一块内存的别名. 下面引自:http://www.cnblogs.com/kingln/articles/1129114.html 从概念上讲.指针从本质上讲就是存放变量地址的一个变量,在逻辑上是独立的,它可以被改变,包括其所指向的地址的改变和其指向的地址中所存放的数据的改变. 而引用是一个别名,它在逻辑上不是独立的,它的存在具有依附性,所以引用必须在一开始就被初始化,而且其引用的对象在其整个生命周期中是不能被改变的(自始至终只能依附于同一

C++二级指针第二种内存模型(二维数组)

C++二级指针第二种内存模型(二维数组) 二维数组 二维数组本质上是以数组作为数组元素的数组,即“数组的数组”. 定义 类型说明符 数组名[常量表达式][常量表达式] 例如: float a[3][4],b[5][10]; 二维数组元素地址 #include <iostream> using namespace std; int main() { cout << "Hello world!" << endl; int a[3][4]={ {1,2,3

关于指针 用字符数组,字符指针变量输入字符串 动态为字符型指针变量分配内存

#include <stdio.h> #include <iostream> #include<math.h> using namespace std; int main() { //声明字符型数组和指针变量 char str[10]; char *strip=str; //输入输出 cout<<"str="; cin>>str; //用字符数组输入字符串 cout<<"str="<<

学习指针变量占用内存字节数相关心得

在学习设置数据收发缓冲区时,做以下实验 void main () { LPBYTE m_data=new BYTE[16]; memcpy(m_data,"example",sizeof(m_data)); string str=" "; str[0]=m_data[3]; cout<<str<<endl; } 函数memcpy(m_data,"example",sizeof(m_data));将“example”在内存中

C++(2)----智能指针与动态内存

C++ 11提供的智能指针有:shared_ptr.unique_ptr.weak_ptr.在 头文件 memory 中. 一.new delete 直接管理内存 1.初始化 string * ps = new string // 初始换为一个空string int * pi = new int ;//pi 指向一个未初始化的int,*pi 未定义 int * pi = new int(1024); // pi 指向的对象值为1024 string *ps = new string(10,'9'

和为S的两个数字(剑指offer)指针O(n)

和为S的两个数字 参与人数:1186时间限制:1秒空间限制:32768K 通过比例:26.97% 最佳记录:0 ms|0K() 题目描述 输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的. 输出描述: 对应每个测试案例,输出两个数,小的先输出. 思路:在递增序列中找两个数使得和为S,积最小,那么那么这两个数的差越大,积越小.我定义两个指针一个指在开头,一个指在结尾,用他们的和与S比较,如果大了,尾指针向前移动:如果小了

2728:摘花生(数字金子塔变形)

2728:摘花生 查看 提交 统计 提问 总时间限制: 1000ms 内存限制: 65536kB 描述 Hello Kitty 想摘点花生送给她喜欢的米老鼠.她来到一片有网格状道路的矩形花生地(如下图),从西北角进去,东南角出来.地里每个道路的交叉点上都有种着一株花生苗,上面有若干颗花生,经过一株花生苗就能摘走该它上面所有的花生.Hello Kitty只能向东或向南走,不能向西或向北走.问Hello Kitty 最多能够摘到多少颗花生. 输入 第一行是一个整数T,代表一共有多少组数据.1<=T