POJ:1050(枚举 + DP)

 1 #include <stdio.h>
 2 #include <math.h>
 3 #include <iostream>
 4 #include <string.h>
 5 #include <algorithm>
 6 using namespace std;
 7 #define N 105
 8 int f[N][N];
 9 int sum[N][N];
10 int main(){
11     int n;
12     while(scanf("%d",&n)!=EOF){
13         memset(f,0,sizeof(f));
14         memset(sum,0,sizeof(sum));
15         for(int i=1;i<=n;i++)
16             for(int j=1;j<=n;j++)  scanf("%d",&f[i][j]);
17         for(int i=1;i<=n;i++)
18              for(int j=1;j<=n;j++){
19                  if(j==1) sum[j][i] = f[j][i];
20                  else sum[j][i] = f[j][i] + sum[j-1][i];
21              }
22         //n最大为100,这里就是简单的将枚举与dp结合起来:
23         //通过枚举从i行到j行, 计算列和之后,每一“行” 进行普通的最长连续子序列求和dp
24         int dp[N];
25         int maxc = (int)-1e9;
26         for(int i=1;i<=n;i++){
27             for(int j=i;j<=n;j++){
28                int num=0;
29                memset(dp,0,sizeof(dp));
30                dp[1] = sum[j][1]-sum[i-1][1];
31                maxc = max(dp[1],maxc);
32                for(int k=2;k<=n;k++){
33                        if(dp[k-1] > 0) dp[k] = dp[k-1] + (sum[j][k]-sum[i-1][k]);
34                        else dp[k] = sum[j][k]-sum[i-1][k];
35                        maxc = max(dp[k],maxc);
36                }
37             }
38         }
39         printf("%d\n",maxc);
40     }
41     return 0;
42 }

·注意看注释即可

时间: 2024-11-29 06:24:51

POJ:1050(枚举 + DP)的相关文章

HDU - 1003 - Max Sum &amp;&amp; POJ - 1050 - To the Max (经典DP问题)

题目传送:HDU - 1003 思路:最大子序列和 dp[i]= a[i]   (dp[i-1]<0) dp[i]= dp[i-1]+a[i]   (dp[i-1]>=0) AC代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <queue> #include

POJ 1050 To the Max DP题解

一维最大字段和的扩展. 要诀是固定列的左右点,比如左边记录为left, 右边记录为right,那么一个循环left从0到COL,行最大值,那么right从left开始循环到COl,就可以考虑到所有列组合了,这个循环是O(n*n),然后求范围列内的行最大子段和,时间是O(n), 这样巧妙地把二维的问题转化为一维了,最终时间复杂度是O(n^3). 可以参考Geeks上的讲解,不过他的最大子段和代码写的挺挫的,我的代码会简洁很多,而且也考虑到了负值情况了. Geeks地址:http://www.gee

POJ 1050 To the Max(DP,最大子矩阵和)

POJ 1050 题意:给一个矩阵,求出元素和最大的子矩阵. 思路: 之前曾写过最大子串和的一篇文章,这次由一维上升到了二维. 我们可以通过累加每行相同列或每列相同行的值,将其储存在一个数组中,便可以将二维降至一维. 时间复杂度为O(n^3). 参考: 累加每一行相同列的做法(java实现) 累加每一列相同行的做法(C++实现) code: /* *Author : Flint_x *Created Time : 2015-07-23 15:10:01 *File name : POJ1050.

POJ 1947 树形DP入门题

给出N个点,N-1个关系,建出树形图,问最少减去几个边能得到节点数为P的树.典型树形DP题 dp[cur][j] :记录cur结点,要得到一棵j个节点的子树去掉的最少边数 转移方程用的背包的思想 对当前树的每一个子树进行计算 砍掉此子树:   dp[cur][j]=dp[cur][j]+1; 不砍掉:           for (l=0;l<=j;l++)  dp[cur][j]=Min(dp[cur][j],dp[cur][l]+dp[next][j-l]); 枚举从该树中留l个节点其他由新

poj 3342(树形dp)

题意:在一个公司中要举办一个聚会,每一个员工有一个奉献值.为了和谐规定直接上下级不能一起出席.让你找出奉献值之和最大为多少. 思路:dp[v][1]表示当前结点选,能获得的最大奉献值,dp[v][0]表示当前节点不选能获得的最大奉献值.状态转移: dp[v][0] = max(dp[v][0], ∑max(dp[x][1], dp[x][0]))x为直接儿子 dp[v][1] = max(dp[v][1], ∑dp[x][0] + vex[v]) 最后答案是max(dp[root][0], dp

poj 2151 概率dp

//poj 2151 概率dp 1 #include "iostream" 2 #include "cstdio" 3 #include "cstring" 4 #include "algorithm" 5 using namespace std; 6 double dp[33][33]; 7 int M, T, N; //problem, team, least 8 double p[1010][33]; 9 int mai

POJ 2250 Compromise (DP,最长公共子序列)

Compromise Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6440 Accepted: 2882 Special Judge Description In a few months the European Currency Union will become a reality. However, to join the club, the Maastricht criteria must be fulfille

poj 1947(树形dp)

题意:一棵树上问你最少切掉几条边使得能分割出一个结点数正好为k的子树. 思路:dp[i][j]表示以i为根切掉j个结点最少要几条边. dp[v][j] = min(dp[v][j], dp[v][j-k] + dp[x][k]); 代码如下: 1 dp[v][j] = min(dp[v][j], dp[v][j-k] + dp[x][k]); 2 } 3 } 4 } 5 } 6 } 7 return vex[v]; 8 } 9 10 int main() 11 { 12 // freopen("

poj 3522 枚举+kruskal

过了样例就能AC 注意一点 0条边特意判断下.是否无法构成生成树也要判断 #include<iostream> #include<stdio.h> #include<string.h> using namespace std; #define maxn 110 int parent[maxn]; int N,M; struct edge { int u,v,w; }edges[maxn*maxn]; int cmp(void const *a,void const *b