动态规划题解——最大子段和专题

A. 最大子段和-DP方法

Description

给出N个数字, 计算出最大的子段和。

Input

第一行给出一个数字 T(1<=T<=20) 代表接下来的组数.

接下来每 T 行,开始给出一个正整数 N(1<=N<=100000), 接着跟着N个整数.。数据保证最后结果小于2^31。

Output

输出最大的字段和

Sample Input

2
5 6 -1 5 4 -7
7 0 6 -1 1 -6 7 -5

Sample Output

14
7

Answer

#include<bits/stdc++.h>
using namespace std;
#define MAXN 100001
#define INF 2000000000
int a[MAXN];
int n,mx;
void vInput();
void vGetMax();
void vOut();
int main() {
	int t,i;
	scanf("%d",&t);
	for(i=1; i<=t; i++) {
		vInput();
		vGetMax();
		vOut();
	}
	return 0;
}
void vInput() {
	int i;
	scanf("%d",&n);
	for(i=1; i<=n; i++) {
		scanf("%d",&a[i]);
	}
}
void vGetMax() {
	int s,i;
	mx=-INF;
	s=0;
	for(i=1; i<=n; i++) {
		if(s<0) {
			s=a[i];
		} else {
			s+=a[i];
		}
		if(s>mx) {
			mx=s;
		}
	}
}
void vOut() {
	printf("%d\n",mx);
}

B. 军训选人问题

Description

很多学校在每年的九月份新学期开学时对新生需要进行军训,我们学校也一样,今年也开始军训了,第一天,总教官把所有新生都召集在一个很大的操场上,把所有学生从1开始依次编号,他要从中选一部分身高符合要求的人参加护旗方队,为了便于管理,他决定符合要求的学生的编号是连续的,他现在想尽可能多选,因为训练中可能会有很多学生由于种种原因而退出,总教官的要求是被选中的同学中任何两个的身高差有限制,不能超过规定的要求。亲爱的同学们,如果你们想帮总教官,那么你就帮他写个程序,计算一下符合要求的学生最多到底是多少?假定学生人数为n(1<=n<=100000),身高h(140<=h<=250),身高的单位是厘米而且是整数。

Input

输入有两行,第一行是学生的人数n和身高的最大允许差,另一行是所有学生的身高。

Output

输出也有两行,第一行的格式是:“From=XX,To=XX”,第二行的格式是:“MaxLen=XX”。本问题有多组测试数据。如果有多组符合要求的解,那么输出所有符合条件的解中起始编号最小的解。

Sample Input

11 15
165 180 187 160 170 180 153 175 190 178 163

Sample Output

From=8,To=10
MaxLen=3

Answer

#include<bits/stdc++.h>
using namespace std;
#define MAXN 100001
int a[MAXN];
int n,mx,from,to,maxLen,small,high;
void vInput();
void vGetMax();
void vOut();
int main() {
	while(2==scanf("%d%d",&n,&mx)) {
		vInput();
		vGetMax();
		vOut();
	}
	return 0;
}
void vInput() {
	int i;
	for(i=1; i<=n; i++) {
		scanf("%d",&a[i]);
	}
}
void vGetMax() {
	int tmpLen,i,tmpFrom;
	maxLen=0;
	for(i=1; i<=n; i++) {
		if(i==1) {
			tmpFrom=i;
			small=a[1]-mx;
			high=a[1]+mx;
			tmpLen=1;
		} else if(a[i]>=small&&a[i]<=high) {
			tmpLen++;
			small=max(small,a[i]-mx);
			high=min(high,a[i]+mx);
		} else {
			tmpLen=1;
			i=tmpFrom+1;
			tmpFrom=i;
			small=a[i]-mx;
			high=a[i]+mx;
		}
		if(tmpLen>maxLen) {
			maxLen=tmpLen;
			from=tmpFrom;
			to=i;
		}
	}

}
void vOut() {
	printf("From=%d,To=%d\n",from,to);
	printf("MaxLen=%d\n",maxLen);
}

C. 军训选人问题(续)

Description

很多学校在每年的九月份新学期开学时对新生需要进行军训,我们学校也一样,今年也开始军训了,第一天,总教官把所有新生都召集在一个很大的操场上,把所有学生从1开始依次编号,他要从中选一部分身高符合要求的人参加护旗方队,为了便于管理,他决定符合要求的学生的编号是连续的,为了方队看上去美观和整齐,他现在想在入选的学生中身高差尽可能小,即总教官的要求是给定被选中的同学的人数,使得在选中的同学中身高的差尽量小。亲爱的同学们,如果你们想帮助总教官,那么你就帮他写个程序,计算一下符合要求的学生身高差最小最多到底是多少?假定学生人数为n(1<=n<=100000),身高h(140<=h<=250),身高的单位是厘米而且是整数。

Input

输入有两行,第一行是学生的总人数n和方队需要的同学人数m(1<=m<=1000),另一行是所有学生的身高。

Output

输出也有两行,第一行的格式是:“From=XX,To=XX”,第二行的格式是:“MinDiff =XX”。本问题有多组测试数据。如果有多组符合要求的解,那么输出所有符合条件的解中起始编号最小的解,如果没有符合要求的解,则输出“No solution !”。

Sample Input

11 4
165 180 187 160 170 180 153 175 190 178 163
11 2
165 180 187 160 170 180 153 175 190 178 163

Sample Output

From=1,To=4
MinDiff=27
From=2,To=3
MinDiff=7

Answer

#include<bits/stdc++.h>
using namespace std;
#define MAXN 100001
#define INF 999999999
int a[MAXN];
int i,j,n,m,from,to,minDiff,small,high;
void vInput();
void vGetMax();
void vOut();
int main() {
	while(2==scanf("%d%d",&n,&m)) {
		vInput();
		if(m>n) {
			cout<<"No solution !"<<endl;
		} else {
			vGetMax();
			vOut();
		}
	}
	return 0;
}
void vInput() {
	int i;
	for(i=1; i<=n; i++) {
		scanf("%d",&a[i]);
	}
}
void vGetMax() {
	minDiff=INF;
	for(i=1; i<=n-m+1; i++) {
		high=-INF;
		small=INF;
		for(j=i; j<=i+m-1; j++) {
			high=max(high,a[j]);
			small=min(small,a[j]);
		}
		if(minDiff>high-small) {
			minDiff=high-small;
			from=i;
			to=i+m-1;
		}
	}
}
void vOut() {
	printf("From=%d,To=%d\nMinDiff=%d\n",from,to,minDiff);
}

D. 字符统计问题

Description

实验室有个胖子叫小明,他第一天进来,老师就叫他练打字,开始练的是打英文字母,小明打了一小时就累啦,老师看他累就叫他不用再练啦,但前提是必须知道他打的英文字母串里连续相同的字符最多到底有几个?亲爱的同学们,如果你们同情胖子小明,那么你就帮他写个程序,计算一下在一个字符串里面连续相同的字符最多到底有多少个?假定字符串都是由英文小写字母组成的,长度不超过100000。

Input

输入是一行字符串。

Output

输出有两行,第一行的格式是:“From=XX,To=XX”,第二行的格式是:“MaxLen=XX”。本问题有多组测试数据。如果有多组符合要求的解,那么输出起始位置最小的解。

Sample Input

isssssssawh
nnnnvaavhhhvv

Sample Output

From=2,To=8
MaxLen=7
From=1,To=4
MaxLen=4

Answer

#include<bits/stdc++.h>
using namespace std;
#define MAXN 100001
int n,mx,from,to,maxLen,small,high;
string s;
void vGetMax();
void vOut();
int main() {
	while(cin>>s) {
		n=s.length();
		vGetMax();
		vOut();
	}
	return 0;
}
void vGetMax() {
	int tmpLen,i,tmpFrom,tmpTo;
	tmpFrom=0;
	tmpTo=0;
	tmpLen=1;
	from=0;
	to=0;
	maxLen=1;
	for(i=1; i<=n; i++) {
		if(s[i]==s[i-1]) {
			tmpTo=i;
			tmpLen++;
		} else {
			if(tmpLen>maxLen) {
				cout<<tmpFrom<<endl;
				cout<<tmpTo<<endl;
				from=tmpFrom;
				to=tmpTo;
				maxLen=tmpLen;
			}
			tmpFrom=i;
			tmpTo=i;
			tmpLen=1;
		}
		if(tmpLen>maxLen) {
			from=tmpFrom;
			to=tmpTo;
			maxLen=tmpLen;
		}
	}
}
void vOut() {
	printf("From=%d,To=%d\n",from+1,to+1);
	printf("MaxLen=%d\n",maxLen);
}
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值