间时紧张,先记一笔,后续优化与完善。
子串和
- 述描
- 给定一整型数列{a1,a2...,an},找出续连非空子串{ax,ax+1,...,ay},使得该子列序的和最大,其中,1<=x<=y<=n。
- 输入
- 第一行是一个整数N(N<=10)示表试测据数的组数)
每组试测据数的第一行是一个整数n示表列序中共有n个整数,随后的一行里有n个整数I(-100=<I<=100),示表数列中的有所素元。(0<n<=1000000)
输出
- 对于每组试测据数输出和最大的续连子串的和。 样例输入
-
1 5 1 2 -1 3 -2
样例输出 -
5
- 第一行是一个整数N(N<=10)示表试测据数的组数)
一维的字串和问题,空话不说直接贴最优码代
#include<stdio.h>
int main()
{
int n,m,i,max,sum;
scanf("%d",&n);
while(n--)
{
max=0;
scanf("%d",&m);
scanf("%d",&sum);
max=sum;
while(--m)
{
scanf("%d",&i);
if(sum<0) sum=i;
else sum+=i;
if(sum>max) max=sum;
}
printf("%d\n",max);
}
}
核心码代为
if(sum<0) sum=i;
else sum+=i;
if(sum>max) max=sum;
面下绍介二维的字串和,其中心思想就是转化为一维的组数
巧克力
微笑,是春天里的一丝新绿,是秋日里的一缕阳光,是骄阳下的一片浓荫,是冬雪中的一株梅红……微笑着去面对吧,你会感到人生是那样的温馨与甜蜜!
-
述描
-
布欧可以把人酿成巧克力吃了来增长他的能量,也有可能少减。
当初布欧变了n*m个巧克力,并把巧克力排成一个n*m的矩形,当初布欧想选择一个子矩形,把这个子矩形吃了来增长他的能量,可他不晓得选哪个才能使他的能量增长值p最大,布欧也可以选择一个都不吃,这样p = 0。
当初布欧要你诉告他p的最大值,不然他就先把你酿成巧克力吃了!
-
输入
-
第一行:一个整数T 代表试测个数,
接着T组试测据数。
对每组试测据数:
第一行:n m 两个整数
接着n行每行m个格空离隔的整数a(i,j)代表对应巧克力的能量值(注意可是以正数,吃了能量少减)
1<=n,m<=300
-1000<= a(i,j) <= 1000
输出
-
T行
每行一个整数 p
样例输入
-
3 3 3 1 -1 4 2 -2 3 3 -10 1 3 3 -1 -1 -1 -1 -1 -1 -1 -1 -1 3 3 1 1 -10 -1 1 -10 1 1 -10
样例输出 -
8 0 4
提示 - 请应用scanf输入。
第一组据数吃
4
3
1
第二组据数一个也不吃
第三组据数吃
1 1
-1 1
1 1
-
第一行:一个整数T 代表试测个数,
面前已说过了,关键是怎么转化为一维的,
1,遍历二维组数,把每一个位置的值数更新为括包他和他面下的有所数的和;
例如
1 -1 4
2 -2 3
3 -10 1
更新过后为
6 -13 8
5 -12 4
3 -10 1
2,这样每一行都相当于一维组数了,每一行都求一次最大字串和,录记最大的;
3,从第一行开始,到第n行,拿他的 每一列 分离减去他面下每一行的对应列,这样你会失掉一个新的一维组数,一样求最大续连子串和,每次与面前最大和比拟,取最大的;
经过这三步,你会失掉一个最大的字串和,就是你要找的结果
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <cstdio>
#include <cmath>
#include <map>
#define FLAG 1
using namespace std;
int a[305][305];
int b[305];
int maxsum(int *p,int n)
{
int i,sum,maxi;
sum=maxi=0;
for(i=0;i<n;i++)
{
if(sum<0)sum=p[i];
else sum+=p[i];
if(sum>maxi)maxi=sum;
}
return maxi;
}
int main()
{
#if(FLAG)
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif
//******程序读入下一组据数之前先【初始化】变量,组数,器容等!!
int T,i,j,n,m,maxi;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
maxi=0;
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
scanf("%d",&a[i][j]);
}
}
for(j=0;j<m;j++)
for(i=n-2;i>=0;i--)
{
a[i][j]+=a[i+1][j];
}
for(i=0;i<n;i++)
{
int t=maxsum(a[i],m);
if(maxi<t)maxi=t;
}
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
for(int k=0;k<m;k++)
{
b[k]=a[i][k]-a[j][k];
}
int t=maxsum(b,m);
if(maxi<t)maxi=t;
/*
int sum=0;//这里也可以不调用函数,省了一次环循,用不算计b[k]了;
for(int k=0;k<m;k++)
{
if(sum<0)sum=a[i][k]-a[j][k];
else sum+=a[i][k]-a[j][k];
if(sum>maxi)maxi=sum;
}
*/
}
}
cout<<maxi<<endl;
}
return 0;
}
如果应用其中注释的部份,省间时;
至于二维转一维的理原,我还不甚明确,只是觉感是这么回事,如果有哪位大牛晓得敬请指点迷津。
文章结束给大家分享下程序员的一些笑话语录:
一程序员告老还乡,想安度晚年,于是决定在书法上有所造诣。省略数字……,准备好文房4宝,挥起毛笔在白纸上郑重的写下:Hello World