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);
}