1. 程式人生 > >poj 1088 滑雪-----DP 動態規劃

poj 1088 滑雪-----DP 動態規劃

滑雪
Time Limit:1000MS Memory Limit:65536K
Total Submissions:57209 Accepted:20771

Description

Michael喜歡滑雪百這並不奇怪, 因為滑雪的確很刺激。可是為了獲得速度,滑的區域必須向下傾斜,而且當你滑到坡底,你不得不再次走上坡或者等待升降機來載你。Michael想知道載一個區域中最長底滑坡。區域由一個二維陣列給出。陣列的每個數字代表點的高度。下面是一個例子
 1  2  3  4 5

16 17 18 19 6

15 24 25 20 7

14 23 22 21 8

13 12 11 10 9

一個人可以從某個點滑向上下左右相鄰四個點之一,當且僅當高度減小。在上面的例子中,一條可滑行的滑坡為24-17-16-1。當然25-24-23-...-3-2-1更長。事實上,這是最長的一條。

Input

輸入的第一行表示區域的行數R和列數C(1 <= R,C <= 100)。下面是R行,每行有C個整數,代表高度h,0<=h<=10000。

Output

輸出最長區域的長度。

Sample Input

5 5
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9

Sample Output

25

中文的,題目意思就不寫了。 - -
我的 解題思路 :用dp[i][j]的值記錄 map[i][j]點 能走的最長的值。  如果一個點周圍都比自己高 或邊界,即為最低點  dp[i][j]即為1,然後其他點根據周圍低的點dp[i][j] 值不斷更新最大值。直到所有點的dp[i][j]都確定。
程式碼:
//Memory: 296 KB		Time: 500 MS
//Language: C++		Result: Accepted
#include<stdio.h>
#include<string.h>
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};      //四個方向
int map[105][105],dp[105][105],vir[105][105];      //map構圖,dp記錄每一個點的最長值,vir標記
int main()
{
//	freopen("in.txt","r",stdin);
	int h,w,i,j,count;
	while(scanf("%d%d",&h,&w)!=EOF)
	{
		memset(vir,0,sizeof(vir));
		count=0;
		for(i=0;i<h;i++)
			for(j=0;j<w;j++)
			{
				scanf("%d",&map[i][j]);
				dp[i][j]=0;          
			}
		while(1)
		{
			for(i=0;i<h;i++)
			{
				for(j=0;j<w;j++)
			   {
				   int big=0,temp=0;    //temp 記錄周圍是否都是確定了最大值的點
				   for(int k=0;k<4;k++)
				   {
					   if(vir[i][j]) continue;
					   int tx=i+dir[k][0],ty=j+dir[k][1]; 
					   if(tx<0||tx>=h||ty<0||ty>=w|| map[tx][ty]>=map[i][j]) 
					   {
						   big++;         //big的值可以理解為 周圍 比這個點高或邊界
						   temp++;
						   continue;
					   }
					   if(map[tx][ty]<map[i][j] && vir[tx][ty])
					   {
						   temp++;
						   if(dp[tx][ty]+1>dp[i][j])    //狀態轉移  總是取較大值
							   dp[i][j]=dp[tx][ty]+1;
					   }
				   }
				   if(big==4) dp[i][j]=1;    //big為4說明是最低點
				   if(temp==4)   //如果周圍的點都已經確認,這個點的值也不在變化,標記,計數.
				   {
					   vir[i][j]=1;
					   count++;
					   if(count==h*w) break;
				   }
			   }
			   if(count==h*w) break;
			}
			if(count==h*w) break;
		}
		int max=0;
		for(i=0;i<h;i++)     //找出最大值
			for(j=0;j<w;j++)
				if(dp[i][j]>max)
					max=dp[i][j];
		printf("%d\n",max);
	}
	return 0;
}