最大子列和,及其扩展最大子矩阵和,都是比较经典的dp,把这两题写在一起,共大家参考学习。
~~~~
lz弱菜啊,到现在还只能写这么水的DP...orz。
~~~~
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1003
http://acm.hdu.edu.cn/showproblem.php?pid=1081
题意应该比较好理解,不解释了。
1003:
#include<cstdio> #include<iostream> #include<cstring> #define INF 1111 #define N 111111 using namespace std; int a[N],dp[N]; int main() { int t,T=0; scanf("%d",&t); while(t--) { int n; scanf("%d",&n); memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++) scanf("%d",&a[i]); dp[n]=a[n]; if(T) puts(""); printf("Case %d:\n",++T); int ans=dp[n],l=n,r=n; for(int i=n-1;i>=1;i--) { dp[i]=max(dp[i+1]+a[i],a[i]); //状态转移 if(ans<=dp[i]) { ans=dp[i]; l=i; //记录最大子序列区间的左端点 } } int s=0; for(int i=l;i<=n;i++) //根据左端点找右端点 { s += a[i]; if(s == ans) { r=i; break; } } printf("%d %d %d\n",ans,l,r); } }
!!DP部分也可以这样写。
for(i=1;i<n;i++) { scanf("%d",&a); if(t<0) t=a; else t=t+a; if(ans<t) ans=t; }
~~~~
1081:
#include<cstdio> #include<cstring> #include<algorithm> #define N 111 #define INF 0x3f3f3f3f using namespace std; int n; int g[N][N],sub[N],f[N]; int dp() { int Max=-INF; f[n-1]=sub[n-1]; for(int i=n-2;i>=0;i--) { f[i]=max(f[i+1]+sub[i],sub[i]); Max=max(Max,f[i]); } return Max; } int qyj() { int ans=-INF; for(int i=0;i<n;i++) //枚举行 { memset(sub,0,sizeof(sub)); //~~ for(int j=i;j<n;j++) { for(int k=0;k<n;k++) { sub[k] += g[j][k]; //子矩阵 } int sum=dp(); //~~ ans=max(ans,sum); } } return ans; } int main() { while(scanf("%d",&n)==1) { for(int i=0;i<n;i++) for(int j=0;j<n;j++) scanf("%d",&g[i][j]); int ans=qyj(); printf("%d\n",ans); } return 0; }
1081不理解的可以手写画画得到子矩阵的那段代码、
HDU 1003 && HDU 1081(最大子列和,最大子矩阵和).,布布扣,bubuko.com
时间: 2024-10-12 22:52:50