最大整数NYOJ 44 字串和 370 巧克力 (最大连续字串和问题)
间时紧张,先记一笔,后续优化与完善。
子串和
间时制约: 5000 ms | 内存制约: 65535 KB
难度: 3
- 述描
- 给定一整型数列{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
一维的字串和问题,空话不说直接贴最优码代
#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;
面下绍介二维的字串和,其中心思想就是转化为一维的组数
巧克力
间时制约:
4000 ms | 内存制约:
65535 KB
难度:
2
- 述描
-
布欧可以把人酿成巧克力吃了来增长他的能量,也有可能少减。
当初布欧变了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
面前已说过了,关键是怎么转化为一维的,
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