1006

背景 Background
    在很久很久以前,有一個動物村莊,那裏是豬的樂園(^_^),村民們勤勞、勇敢、善良、團結…… 
   不過有一天,最小的小小豬生病了,而這種病是極其罕見的,因此大家都沒有儲存這種藥物。所以晴天小豬自告奮勇,要去採取這種藥草。於是,晴天小豬的傳奇故事便由此展開…… 
 描述 Description
    這一天,他來到了一座深山的山腳下,因爲只有這座深山中的一位隱者才知道這種藥草的所在。但是上山的路錯綜複雜,由於小小豬的病情,晴天小豬想找一條需時最少的路到達山頂,但現在它一頭霧水,所以向你求助。 
   山用一個三角形表示,從山頂依次向下有1段、2段、3段等山路,每一段用一個數字T(1<=T<=100)表示,代表晴天小豬在這一段山路上需要爬的時間,每一次它都可以朝左、右、左上、右上四個方向走(**注意**:在任意一層的第一段也可以走到本層的最後一段或上一層的最後一段)。 
   晴天小豬從山的左下角出發,目的地爲山頂,即隱者的小屋。
 輸入格式 Input Format
    第一行有一個數n(2<=n<=1000),表示山的高度。 
   從第二行至第n+1行,第i+1行有i個數,每個數表示晴天小豬在這一段山路上需要爬的時間。
 輸出格式 Output Format
    一個數,即晴天小豬所需要的最短時間。

也是一個動態規劃的問題,但是自己對於動態規劃的理解還是不夠,各種窘迫,又一次不得不去參看別人的代碼,由於自己水平比較低下,好多別人的代碼都理解不了, 有些效率高的代碼設計的很精巧,理解起來也極爲困難,與之相對,一些容易理解的代碼的效率也就不是很高了。最後自己找了一個暴力DP的思想來求解這個問題,期間的問題也是多多,各種被卡,直到很晚,纔在博客園一位大牛的博客的啓發下修改正確,這個問題將會着重討論。動態規劃啊,啥時候能有點感覺啊……

仍然無恥的把自己的代碼貼出來。

#include <stdio.h>
 //#include <Windows.h>
 
 int a[1001][1001];
 long int step[1001][1001];
 int main()
 {
 	int n,i,j,flag = 0;
 	scanf("%d",&n);
 	for (i=1;i<=n;i++)
 	{
 		for(j=1;j<=i;j++)
 		{
 			scanf("%d",&a[i][j]);
 			step[i][j] = 100000;
 		}
 	}
 	step[1][0] = a[1][1];
 	step[1][2] = a[1][1];
 	for (i=2;i<=n;i++)
 	{
 		while(1)
 		{	
 			step[i][0] = step[i][i];
 			step[i][i+1] = step[i][1];
 			flag = 1;
 			for (j=1;j<=i;j++)
 			{
 				//
 				if (step[i][j]>step[i-1][j]+a[i][j])
 				{
 					step[i][j] = step[i-1][j]+a[i][j];
 					flag = 0;
 				}
 				if (step[i][j]>step[i-1][j-1]+a[i][j])
 				{
 					step[i][j] = step[i-1][j-1]+a[i][j];
 					flag = 0;
 				}
 				if (step[i][j]>step[i][j-1]+a[i][j])
 				{
 					step[i][j] = step[i][j-1]+a[i][j];
 					flag = 0;
 				}
 				if (step[i][j]>step[i][j+1]+a[i][j])
 				{
 					step[i][j] = step[i][j+1]+a[i][j];
 					flag = 0;
 				}
 			}
 			if (flag == 1)
 				break;
 		}
 
 	}
 
 	printf("%ld",step[n][1]);
 	//system("pause");
 	return 0;
 
 }
備註:

  1. 首先就是對於題意的理解出現了問題,題目表述不清楚,走的四個方向就把我整暈了,左右好理解,左上右上是啥回事,後來纔想明白是三角錐形的排列方式,如下圖,每行數據還是圓形排列,就像一個圓錐。
     
    本題可以採用自上而下或者自下而上兩種方式來求解,我們採用自上而下的方式。根據上圖的排列我們可構造出動態規劃方程
    step[i][j] = min{step[i][j-1]+a[i][j],step[i][j+1]+a[i][j],step[i-1][j-1]+a[i][j],step[i][j]+a[i][j]}
  2. 在程序實現的過程中一再的報錯,提示stack overflow,昨天的青蛙過河是由於遞歸層次太多導致堆棧溢出,這個程序也沒有10^9這麼大的數據,遞歸也沒有用到,問題最後歸結到了開篇那個數組身上,一開始將其聲明爲局部變量,後來改爲全局變量程序才得以通過。原來windows32位操作系統給程序的棧、堆分配的空間默認爲1M。我開闢的數組爲step[1000][1000],假設爲int類型的話,step佔空間爲4*1000*1000Byte 大約是3M多一點。出現越界也是必然的了。關於這個問題將會細緻的討論一下。參見文章程序中關於堆棧的劃定
    總結:在寫程序的時候要有空間觀念,大小超過1M的變量儘量定義爲全局變量或者靜態變量。


 
 
發佈了46 篇原創文章 · 獲贊 102 · 訪問量 47萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章