最大连续子串&子矩阵
2012-09-11 19:06
295 查看
最大连续子串
hdu1003
最普通的版本
dp[i]=max{ dp[i-1]+dat[i] , dat[i] }
对于当前的数字dat[i], 有两种选择
A.原子串增长,dp[i]=dp[i-1]+dat[i]
~~~~~前提是dat[i]<=dp[i-1]+dat[i]
B.原子串结束,以dat[i]为起点开始新子串。
~~~~~前提是dat[i]>dp[i-1]+dat[i]
注:以原子串的长度来划分有三种情况。
1.增长 对应上文选择中的A
2.不变 对应B,这种长度不变的情况是不符合题意的,因为题目要求子串连续,也就是说面对新的数字dat[i] 要么同化(dp[i]=dp[i-1]+dat[i]),要么异化(dp[i]=dat[i])
不能忽略~比如 dat[1]=10,dat[2]=20,dat[3]=-100,那么dp[1]=10 dp[2]=30 dp[3]=-70 ,答案max=dp[2]=30......
3.减短,,,,,,,算了吧
练习
hdu1231
hdu1024
M个子串最大和
dp[i][j] = max(dp[i][j-1] , dp[i-1][t] )+ dat[j] (i<=k<j)
感觉蛮难理解的, 参考
递增子串
hdu1087
pku2533最长递增子序列
注意初始化
最大子矩阵和
hdu1081
11~17行预处理
计算出dp[i][j],表示第i行前j个数的和。
20~32行 dp
前两层循环遍历i,j所有可能的组合
得到的每一组(i,j)表示矩阵的第i~j列,相当于hdu1003的一组数据
参考
hdu1559
穷举
hdu1003
最普通的版本
dp[i]=max{ dp[i-1]+dat[i] , dat[i] }
对于当前的数字dat[i], 有两种选择
A.原子串增长,dp[i]=dp[i-1]+dat[i]
~~~~~前提是dat[i]<=dp[i-1]+dat[i]
B.原子串结束,以dat[i]为起点开始新子串。
~~~~~前提是dat[i]>dp[i-1]+dat[i]
注:以原子串的长度来划分有三种情况。
1.增长 对应上文选择中的A
2.不变 对应B,这种长度不变的情况是不符合题意的,因为题目要求子串连续,也就是说面对新的数字dat[i] 要么同化(dp[i]=dp[i-1]+dat[i]),要么异化(dp[i]=dat[i])
不能忽略~比如 dat[1]=10,dat[2]=20,dat[3]=-100,那么dp[1]=10 dp[2]=30 dp[3]=-70 ,答案max=dp[2]=30......
3.减短,,,,,,,算了吧
#include<iostream> using namespace std; int main() { int t,T,i,j,N,now,max,temp,begin,end,x; scanf("%d",&T); for(t=1;t<=T;t++) { scanf("%d%d",&N,&temp); now=max=temp; begin=end=x=1; // printf("i1 temp%d now%d x%d max%d begin%d end%d \n",temp,now,x,max,begin,end); for(i=2;i<=N;i++) { scanf("%d",&temp); if(temp>now+temp) now=temp,x=i; //即if(now<0) now=temp,x=i; else now+=temp; if(max<now) { begin=x; end=i; max=now; } // printf("i%d temp%d now%d x%d max%d begin%d end%d \n",i,temp,now,x,max,begin,end); } printf("Case %d:\n%d %d %d\n",t,max,begin,end); if(t!=T) printf("\n"); } return 0; }
练习
hdu1231
#include<stdio.h> int main() { int i,n,temp,now,max,begin,x,end,flag,flagBegin,flagEnd; while(scanf("%d",&n),n) { flag=1; scanf("%d",&temp); flagBegin=temp; if(temp>=0) flag=0; x=begin=end=now=max=temp; for(i=2;i<=n;i++) { scanf("%d",&temp); if(temp>=0) flag=0; if(temp>now+temp) x=now=temp; else now+=temp; if(max<now) max=now,begin=x,end=temp; } flagEnd=temp; if(flag) printf("%d %d %d\n",0,flagBegin,flagEnd); else printf("%d %d %d\n",max,begin,end); } return 0; }
hdu1024
M个子串最大和
dp[i][j] = max(dp[i][j-1] , dp[i-1][t] )+ dat[j] (i<=k<j)
感觉蛮难理解的, 参考
#include<iostream> #include<algorithm> using namespace std; int dpmax[1000005],dp[1000005],dat[1000005]; int main() { int i,j,m,n,MAX; while(scanf("%d%d",&m,&n)!=EOF) { for(i=1;i<=n;i++) scanf("%d",&dat[i]); memset(dpmax,0,sizeof(dpmax[0])*n+4); for(i=1;i<=m;i++) { MAX=-99999999; for(j=i;j<=n;j++) { dp[j]=max(dpmax[j-1],dp[j-1])+dat[j]; dpmax[j-1]=MAX; if(MAX<dp[j]) MAX=dp[j]; } dp[j-1]=MAX;//也可以写成dp[j-1]=max(dpmax[j-2],dp[j-1]); 不理解 } printf("%d\n",dp ); } return 0; }
递增子串
hdu1087
#include<stdio.h> #include<string.h> int num[1001],dp[1001]; int main() { int m,n,i,j,sum; num[0]=0; while(scanf("%d",&n),n) { memset(dp,0,sizeof(dp)); for(i=1;i<=n;i++) { scanf("%d",&num[i]); for(j=0;j<i;j++) { if(num[j]<num[i]&&dp[i]<dp[j]+num[i]) dp[i]=dp[j]+num[i]; } } //for(i=1;i<=n;i++) // printf("%d ",dp[i]);printf("\n"); for(dp[n+1]=j=0;j<=n;j++) if(dp[n+1]<dp[j]) dp[n+1]=dp[j]; printf("%d\n",dp[n+1]); } return 0; }
pku2533最长递增子序列
注意初始化
#include<stdio.h> #include<string.h> int dp[1001],n[1001]; int main() { int i,j,N; n[0]=0; while(scanf("%d",&N)!=EOF) { for(i=1;i<=N;i++) { scanf("%d",&n[i]); dp[i]=1; for(j=1;j<i;j++) { if(n[j]<n[i]&&dp[i]<dp[j]+1) dp[i]=dp[j]+1; } // for(j=0;j<=N;j++) // printf("%d ",dp[j]);printf("\n"); } for(dp[0]=0,i=1;i<=N;i++) if(dp[0]<dp[i]) dp[0]=dp[i]; printf("%d\n",dp[0]); } return 0; }
最大子矩阵和
hdu1081
11~17行预处理
计算出dp[i][j],表示第i行前j个数的和。
20~32行 dp
前两层循环遍历i,j所有可能的组合
得到的每一组(i,j)表示矩阵的第i~j列,相当于hdu1003的一组数据
参考
#include<stdio.h> #include<string.h> int dp[105][105]; int main() { int i,j,k,N,sum,max; while(scanf("%d",&N)!=EOF) { memset(dp,0,sizeof(dp)); for(i=1;i<=N;i++) for(j=1;j<=N;j++) { scanf("%d",&sum); dp[i][j]+=dp[i][j-1]+sum; } max=-99999999; for(i=1;i<=N;i++) { for(j=i;j<=N;j++) { sum=0; for(k=1;k<=N;k++) { if(sum<0) sum=dp[k][j]-dp[k][i-1]; else sum+=dp[k][j]-dp[k][i-1]; if(max<sum) max=sum; } } } printf("%d\n",max); } return 0; } /* 4 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 */
hdu1559
穷举
#include<iostream> using namespace std; int sum[1005][1005]; int main() { int T,m,n,x,y,i,j,k,max,num; scanf("%d",&T); while(T--) { scanf("%d%d%d%d",&m,&n,&x,&y); memset(sum,0,sizeof(sum)); for(i=1;i<=m;i++) { for(j=1;j<=n;j++) { scanf("%d",&max); sum[i][j]=sum[i][j-1]+max; } } max=0; for(i=1;i<=m-x+1;i++) { for(j=1;j<=n-y+1;j++) { num=0; for(k=0;k<y;k++) num+=sum[i+k][j+y-1]-sum[i+k][j-1]; if(max<num) max=num; } } printf("%d\n",max); } return 0; }
相关文章推荐
- NYOJ 44 & 104 - 最大连续子串和(矩阵最大子矩阵和)
- POJ 2479 Maximum sum & POJ 2573 Max Sequence (DP,最大连续子串和)
- 美团2017编程题—拼凑钱币&大富翁游戏&最大矩形面积&最长公共连续子串
- HDU 1003 Max Sum && HDU 1081 To The Max 一维子串最大和& 二维矩阵最大和
- UVa 507 Jill Rides Again (贪心&最大连续子串和)
- 动态规划题目(三)——最大连续乘积子串
- Poj 3693 & Hdu 2459 Maximum repetition substring (08合肥Online 后缀数组+RMQ 重复次数最多的连续重复子串)
- 最大子序列、最长连续公共子串(连续)、最长公共子序列(动态规划)
- 最大连续子串和(DP)
- 一道C语言面试题——求最大连续数字子串
- 求最大连续子串
- hdoj 1003 连续最大子数组 分治法 & dp法
- SPOJ GSS1 && GSS3 (无更新/更新单点,并询问区间最大连续和)
- 最大连续子串和
- 连续子串的最大值(经典的DP问题)
- 连续子串的最大值(经典的DP问题)
- UVa 10827 Maximum sum on a torus (贪心&矩阵环中的最大子矩阵和)
- 用三重循环求一个字符串的最大回文串(连续重复出现的最长子串)
- JAVA :在给定一个数组中,可以取得多个连续的子串。在众多子串中,求各元素和为最大值的连续子串!
- 【BZOJ 1084】【SCOI 2005】最大子矩阵【DP & 分类讨论】