ACM-游玩景点(AC,动态规划,最大子序列和问题)

游玩景点

Time Limit:1000MS  Memory Limit:65536K
Total Submit:182 Accepted:35

Description

DieIng五一要去旅游,旅游区的景点道路分布如图:欣赏景点的道路为东西走向,每条道路有DieIng对它的喜爱值;南北走向为林间小道,供休息用。
由于五一游客较多,旅游区规定欣赏景点的道路只能单向行走,自东向西走;林间小道可双向行走。
DieIng要你帮他设计路线(可以从任意点开始,任意点结束),使得他能玩得最high。(喜爱值的总和最大)

Input

第一行是两个整数N(0 <= N <= 10) 和M(0 <= M <= 1000000), 代表旅游区的布局,N*M
接下来N行,每行有M个整数favorite(-100 <= favorite<=100)
N,M==0结束。

Output

输出DieIng能得到最大的喜爱值总和。

Sample Input

3 4
5 -4 6 14
-2 -48 11 -8
9 -13 4 8
0 0

Sample Output

30

Source

GDUT Programming Contest 2009 by longshen

 

 


/*	----------------------------------------------------------------------------------
	大概想法:
	
	1、看到的题目的要输入最大值的时候,第一感觉就是要用DP或者贪心来做,然后再去看看有
	   没有最优子结构什么的,果然有,最后通过的景点最大值必然是以最大值通过前一个景点,
	   然后什么独立子问题的不会分析,先试试用DP。
	
	2、在写递归解的时候,突然间觉得这个题目貌似见过。题目的示例输出是30,也就是每一列的
	   最大值加起来。如果用暴力法求解的话,就需要遍历出每一列的最大值,然后根据逐一相加
	   求出最大值,这样做的话估计会超时。可不可以降低时间复杂度?刚才说到了“其实就是求
	   出每一列的最大值”,这一句提示了我。我可以求出每一列的最大值,然后将它们放到另外
	   一个数组中或者覆盖原数组中该元素的位置,从而构造出一个由列最大值组成的数组,然后
	   再来看看,这一个问题其实就转化为求最大子数组之和的问题。
	   详细见代码
		

	----------------------------------------------------------------------------------	*/



#include<stdio.h>

#define max(x,y) ((x)>(y) ? (x) : (y))

long a[1000004] ;
long b[1000004] ;			//空间其实也可以优化,覆盖原来的位置

int main(void)
{
	long N = 0 ;
	long M = 0 ;
	long i = 0 ;
	long j = 0 ;
	long nFavSum = 0 ;
	long nTemp = 0 ;
	long nTotal = 0 ;
	
	while(scanf("%ld%ld",&N,&M), (N != 0 && M != 0))
	{
		nFavSum = 0 ;
		nTemp = 0 ;
		nTotal = 0 ;

		for(i = 0 ; i < N ; ++i)
		{
			for(j = 0 ; j < M ; ++j)
			{
				scanf("%ld",&nTemp) ;
				
				if(0 == i)
				{
					a[nTotal++] = nTemp ;
				}
				else if(nTemp > a[j])
				{
					a[j] = nTemp ;
				}
			}		
		}
		
		b[0] = a[0] ;
		nFavSum = 0 ; 

		for(i = 1 ; i < M ; ++i)
		{
			b[i] = max(a[i],b[i-1]+a[i]) ;

			if(nFavSum < b[i])
			{
				nFavSum = b[i] ;
			}
		}	
		printf("%ld\n",nFavSum) ;
	}
	return 0 ;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值