DP动态规划——最大数字子串

http://acm.nankai.edu.cn/p1760.html


最大数字子串


Time Limit: 1500 ms    Memory Limit:10000 kB  
Judge type: Multi-cases
Total Submit : 1215 (245 users)   Accepted Submit :397 (209 users)   Page View : 6115 

Font Style:AaAaAa

输入n(1<=n<=1e6)和n个整数,这n个整数的绝对值均小于1000,求最大数字子串之和。

Input

输入为多组样例数据,每组第一行为一个正整数n,第二行为n个整数组成的数字串。

Output

对于每组样例,输出仅为一行,表示最大数字子串的各项之和。

Sample Input

9

-3 4 9 2 -10 -7 11 3 -8

13

-1 2 6 -3 5 -7 14 -5 -15 1 8 -4 9

Sample Output

15

17

Hint

在第一组中,最大的数字子串是4 9 2的和
在第二组中,最大的数字子串是2 6 -3 5 -7 14的和


方法:

-3   4  9   2   -10  -7   11   3   -8

记录方法:

   -3  4   13  15  5     -7    11  14  6

   把当前的最大和(含当前末尾的最大和)记录下来,虽然不能直接得出最大和是多少,但可以进行遍历搜索最大值即可!

v     关键是要对负数处理好,看例二,最大子串含有负数。

-12 6 -3 5 -7 14 -5 -15 1 8 -4 9

-12 8

如果在此处断开记录-3,那么前面的26两个正数就和后边断开了,实际上2+6+-3>0,如果后边是正数的话,完全可以加上这3个数(比如后边的5

-12 8 5 10

相同处理: -1 2 8 5 10 317 12

后面是-15,加上12(前面的子串能形成的最大和)也小于0,所以此处应该断开了!记录-15

最后-1 2 8 5 10 3 1712 -15 1 8 4 13

 

 

v    输入数组a[i],用数组s[i]记录最后一个数为a[i]时的最大子串和

v    状态转移方程为  

v    s[i] = max(s[i-1]+a[i],a[i]); 1<=i<n-1  

v    初始条件s[0]=a[0]

v    然后s[i]中最大元素即为所求。 

 

AC代码:

 

#include<stdio.h>
int a, s;
int main()
{
	int i,n,num;
	while(~scanf("%d",&n))
	{
		scanf("%d",&s);
		num=s;
		for(i=1;i<n;i++)
		{
			scanf("%d",&a);
			if(s<0)
				s=a;
			else
				s+=a;
			if(num<s) num=s;
		}
		printf("%d\n",num);
	}
	return 0;
}


 

 

TLE代码:


#include<stdio.h>
int a[2000000],s[2000000];
int main()
{
	int i,n,num;   //num记录最大值
	while(~scanf("%d",&n))
	{
		for(i=0;i<n;i++)
			scanf("%d",&a[i]);
		num=s[0]=a[0];
		for(i=1;i<n;i++)
			if(s[i-1]<0)
				s[i]=a[i];
			else
				s[i]=s[i-1]+a[i];
		for(i=1;i<n;i++)
			if(num<s[i]) num=s[i];
		printf("%d\n",num);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>