HDU 1081 To The Max【dp,思维】
题意:给定二维矩阵,求数组的子矩阵的元素和最大是多少。
题解:这个相当于求最大连续子序列和的加强版,把一维变成了二维。
先看看一维怎么办的:
int getsum()
{
int tot=;
int ans=-1e9;
for(int i=;i<=n;i++){
if(tot<) tot=;
tot+=a[i];
if(tot>ans)
ans=tot;
}
return ans;
}
这种做法太棒了!短短几行,就能解决最大子序列和这个问题。其实这几行代码值得深思。而且这是个在线算法,输入数据及时能给出结果,感觉不能归于动归解法。
但当求解这道题时,就不知道怎么办了。我当时受到以前做的一道关于求01矩阵最大0子矩阵面积的题的启发,想先预处理每行得到前缀和数组,然后再想办法dp。可是dp状态和方程一直找不好。后来看到别人的解法才明白,他们其实也是预先处理的每行的前缀和。他们的想法就是先求出每行的前缀和数组sum[][],然后依次枚举前k行的第i列到第j列的和,求最大值。感觉就像是枚举出了每一个子矩阵,像暴力>_<.
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = ;
int sum[MAXN][MAXN]; int main()
{
int N, tmp;
while (scanf("%d", &N) == )
{
memset(sum, , sizeof(sum));
for (int i = ; i <= N; i++)
for (int j = ; j <= N; j++)
{
scanf(" %d", &tmp);
sum[i][j] = sum[i][j - ] + tmp;//预处理得到每行的前缀和
}
int ans = -1e9;
for (int i = ; i <= N; i++) {//从第i列
for (int j = i; j <= N; j++) {//到第j列
int tot = ;
for (int k = ; k <= N; k++)//前k行
{
if (tot < ) tot = ;
tot += sum[k][j] - sum[k][i - ];//第i列到第j列的和
if (ans < tot)
ans = tot;
}
}
}
printf("%d\n", ans);
}
return ;
}
当然,可以前k行第i列到第j列就可以前k列第i行到第j行,其实是一样的:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = ;
int sum[MAXN][MAXN]; int main()
{
int N,tmp;
while (scanf("%d",&N)==)
{
memset(sum, , sizeof(sum));
for(int i=;i<=N;i++)
for (int j = ; j <= N; j++)
{
scanf(" %d", &tmp);
sum[i][j] = sum[i-][j] + tmp;
}
int ans = -1e9;
for (int i = ; i <= N; i++) {
for (int j = i; j <= N; j++) {
int tot = ;
for (int k = ; k <= N; k++)
{
if (tot < ) tot = ;
tot += sum[j][k] - sum[i-][k];
if (ans < tot)
ans = tot;
}
}
}
printf("%d\n", ans);
}
return ;
}
按前k列想
也有人按照矩阵压缩的想法写,我觉得实际上还是上面的做法,而且上面的想法更容易理解。因为这里所谓矩阵压缩也就是几行加在一起求最大连续子序列。虽殊途同归,但毕竟想法不一样,代码上就会稍微有点差别:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=;
int a[MAXN][MAXN],tmp[MAXN];
int N; int getsum()
{
int tot=,mx=;
for(int i=;i<=N;i++){
tot+=tmp[i];
if(tot>mx) mx=tot;
if(tot<) tot=;
}
return mx;
} int main()
{
while(scanf("%d",&N)==)
{
int temp;
for(int i=;i<=N;i++)
for(int j=;j<=N;j++)
scanf("%d",&a[i][j]);
int ans=-1e9;
for(int i=;i<=N;i++)
{
memset(tmp,,sizeof(tmp));
for(int j=i;j<=N;j++)
{
for(int k=;k<=N;k++)
tmp[k]+=a[j][k];
int tot=getsum();
if(ans<tot)
ans=tot;
}
}
printf("%d\n",ans);
} return ;
}
按矩阵压缩的想法
还有人用树状数组写,我觉的也很棒。没想到我第一次用到二维树状数组是再做dp题的时候。。。虽然这是伪装成二维树状数组的,因为只更新了一维。按照我的理解二维树状数组就是存了若干个一维树状数组的和。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=;
int sum[MAXN][MAXN]={};
int N; int Lowbit(int x)
{
return x&-x;
} void Add(int i,int j,int val)
{
while(j<=N){
sum[i][j]+=val;
j+=Lowbit(j);
}
return;
} int Sum(int k,int x)
{
int cnt=;
while(x>){
cnt+=sum[k][x];
x-=Lowbit(x);
}
return cnt;
} int main()
{
while(scanf("%d",&N)==)
{
int tmp;
memset(sum,,sizeof(sum));
for(int i=;i<=N;i++)
for(int j=;j<=N;j++){
scanf("%d",&tmp);
Add(i,j,tmp);
}
int ans=-1e9;
for(int i=;i<=N;i++)
{
for(int j=i;j<=N;j++){
int tot=;
for(int k=;k<=N;k++){
if(tot<) tot=;
tot+=Sum(k,j)-Sum(k,i-);
if(ans<tot)
ans=tot;
}
}
}
printf("%d\n",ans);
} return ;
}
当然,加个dp数组看起来更像是dp题。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = ;
int sum[MAXN][MAXN];
int dp[MAXN];
int N; int lowbit(int x)
{
return x&-x;
} void add(int i, int j, int d)
{
while (j <= N)
{
sum[i][j] += d;
j += lowbit(j);
}
return;
} int Sum(int k, int x)
{
int cnt = ;
while (x>)
{
cnt += sum[k][x];
x -= lowbit(x);
}
return cnt;
} int main()
{
int tmp;
while (scanf("%d",&N)==)
{
memset(sum, , sizeof(sum));
for(int i=;i<=N;i++)
for (int j = ; j <= N; j++)
{
scanf(" %d", &tmp);
add(i, j, tmp);
}
int ans = -1e9;
for (int i = ; i <= N; i++) {
for (int j = i; j <= N; j++) {
memset(dp, , sizeof(dp));
for (int k = ; k <= N; k++) {
tmp = Sum(k, j) - Sum(k, i-);
if (dp[k - ] > )
dp[k] = dp[k - ] + tmp;
else
dp[k] = tmp;
ans = max(ans, dp[k]);
}
}
}
printf("%d\n", ans);
}
return ;
}
加个dp[]数组
参考博客(感谢~):
【1】:http://blog.csdn.net/acmman/article/details/38580931?spm=5176.100239.blogcont18950.3.TbcH0h
【2】:http://www.cnblogs.com/cenariusxz/p/4309627.html
【3】:http://www.cnblogs.com/gaigai/archive/2012/03/04/2379728.html
HDU 1081 To The Max【dp,思维】的更多相关文章
- URAL 1146 Maximum Sum & HDU 1081 To The Max (DP)
点我看题目 题意 : 给你一个n*n的矩阵,让你找一个子矩阵要求和最大. 思路 : 这个题都看了好多天了,一直不会做,今天娅楠美女给讲了,要转化成一维的,也就是说每一列存的是前几列的和,也就是说 0 ...
- hdu 1081 To The Max(dp+化二维为一维)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1081 To The Max Time Limit: 2000/1000 MS (Java/Others ...
- HDU 1081 To The Max (dp)
题目链接 Problem Description Given a two-dimensional array of positive and negative integers, a sub-rect ...
- hdu 1081 To The Max(二维压缩的最大连续序列)(最大矩阵和)
Problem Description Given a two-dimensional array of positive and negative integers, a sub-rectangle ...
- HDU 1081 To the Max 最大子矩阵(动态规划求最大连续子序列和)
Description Given a two-dimensional array of positive and negative integers, a sub-rectangle is any ...
- dp - 最大子矩阵和 - HDU 1081 To The Max
To The Max Problem's Link: http://acm.hdu.edu.cn/showproblem.php?pid=1081 Mean: 求N*N数字矩阵的最大子矩阵和. ana ...
- Hdu 1081 To The Max
To The Max Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total ...
- HDU 2476 String painter(区间DP+思维)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2476 题目大意:给你字符串A.B,每次操作可以将一段区间刷成任意字符,问最少需要几次操作可以使得字符串 ...
- HDU 1081 To The Max(动态规划)
题目链接 Problem Description Given a two-dimensional array of positive and negative integers, a sub-rect ...
随机推荐
- Puppet master-agent模型搭建
Puppet master-agent模型工作过程: 基于ssl xmlrpc进行通信,端口8140/tcp agent:默认每隔30分钟向master发送node name和facts,并请求cat ...
- 查看linux系统的文件inode号码使用情况
:~$ df -i 文件系统 Inode 已用(I) 可用(I) 已用(I)% 挂载点 udev % /dev tmpfs % /run /dev/sda2 % / tmpfs % /dev/shm ...
- Django项目:CRM(客户关系管理系统)--45--37PerfectCRM实现King_admin添加用户时密码加密
#views # ————————02PerfectCRM创建ADMIN页面———————— from django.shortcuts import render # ————————04Perfe ...
- TZ_05_Spring_基于AOP的xml配置
1.分析 1>首先我们有一个Service需要增强 将Service增加一个日志(Logger) 2>写了一个日志的通知并且它可以对Service进行日志增强 ...
- CSP-S模拟 - 20190916
这是一套题=.= ABC D1DEF D2 过程-Process Before T1 像DP 迷茫…… T2 像二/三分 T3 不知道惹 可以DP($30\%$) During T1 先打个暴力$N^ ...
- 20190719-FirstZero
这也许也是一个成就吧? First Zero 考试 第一次 爆0 好了好了. T1 你永远不知道你在想什么. 我仿佛想出一个$\Theta(NM\log^2 N)$的$dfs$??? 蒟蒻原地爆炸 T ...
- netbeans性能分析文件保存位置
C:\Users\Administrator\AppData\Roaming\NetBeans\8.2\config\HTTPMonitor 分析完,记得把文件删除,不然系统盘要满了
- ArrayList,LinkedList,Vestor
Collection是最基本的集合接口,声明了适用于JAVA集合的通用方法,list和set都继承自collection接口. Collection接口的方法 boolean add(Object o ...
- JavaScript Libraries In A TypeScript Application, Revisited
If you haven’t already gotten involved with it, you’ll probably know that TypeScript is becoming inc ...
- Poj 2104区间第k大(归并树)
题目链接 K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 36890 Accepted: 11860 C ...