最大01子矩阵和,就是一个矩阵的元素不是0就是1,然后求最大的子矩阵,子矩阵里的元素都是相同的。

这个题目,三个oj有不同的要求,hoj的要求是5s,poj是3秒,hdu是1秒。不同的要求就对应不同的难度,不同的逼格。

先看最low的,

HOJ 1664

5秒钟的时间,够长了。我很容易想到可以最大子矩阵和来求解,二者本来就很像,关于最大子矩阵和这个博客里有介绍

最大子矩阵和

这里我们可以把F变成1,把R变成负无穷大,这样求解最大子矩阵和就可以得到答案

#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <algorithm> using namespace std;
#define MAX -1005
int a[1005][1005];
int dp[1005];
int c[1005];
char b[105];
int n,m;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
// getchar();
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%s",b);
if(b[0]=='R')
a[i][j]=MAX;
else if(b[0]=='F')
a[i][j]=1;
}
//getchar();
}
int ans=0;
for(int i=1;i<=n;i++)
{
memset(c,0,sizeof(c));
memset(dp,0,sizeof(dp));
for(int k=i;k<=n;k++)
{
for(int j=1;j<=m;j++)
{
c[j]+=a[k][j];
if(dp[j-1]>=0)
dp[j]=dp[j-1]+c[j];
else
dp[j]=c[j];
ans=max(ans,dp[j]);
}
}
}
printf("%d\n",ans*3);
}
return 0;
}

这个代码在poj上也可以过大概是2秒多,差一点就超时。效率是O(n^3).



但是我们怎么能止步于此呢!

接下来这道题目可以用O(n^2)效率解决。首先F是1,R是0。其思想是把1看成一个方块,0自然就没有方块,整个矩阵从第一维开始,然后逐维的加上,就是一排高度不一的矩形。从这一排矩形找到可以形成的最大矩形,就是转换为poj2082 可以看这篇博客

POJ 2082

#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <algorithm> using namespace std;
#define MAX 1000
int a[MAX+5][MAX+5];
int c[MAX+5];
int n,m;
char b[25];
int ans;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
//getchar();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%s",b);
if(b[0]=='F')
a[i][j]=1;
else
a[i][j]=0;
}
//getchar();
}
memset(c,0,sizeof(c));
ans=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i][j]==1)
c[j]++;
else
c[j]=0;
}
int sum=0;
for(int k=1;k<=m;k++)
{
int num=0;
for(int p=k-1;p>=1;p--)
{
if(c[p]>=c[k])
num++;
else
break;
} for(int q=k+1;q<=m;q++)
{
if(c[q]>=c[k])
num++;
else
break;
}
num++;
num*=c[k];
//cout<<num<<endl;
sum=max(sum,num);
}
ans=max(ans,sum);
//printf("%d\n",ans);
}
printf("%d\n",ans*3);
}
return 0;
}



果然快了1秒多,但是HDU里要求是1秒,但是hdu的数据没有那么大,这个代码交到hdu是可以过的,但是我们怎么可以止步于此,于是我们探究O(n)效率的算法。

其实把这道题目和poj 2082联系在一起就知道O(n)效率怎么写的了,利用单调栈,在求一排高度不等的矩形求形成最大矩形的效率是O(n).



根据递增的单调栈,如果当前栈顶的矩形高度高直接入栈



如果低于栈顶的矩形,那就出栈直到栈顶矩形高度低于当前矩形

#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <algorithm> using namespace std;
#define MAX 1000
int a[MAX+5][MAX+5];
int c[MAX+5];
int n,m;
char b[25];
int ans;
int s[MAX+5];
int l[MAX+5];
int rear;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
//getchar();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%s",b);
if(b[0]=='F')
a[i][j]=1;
else
a[i][j]=0;
}
//getchar();
}
memset(c,0,sizeof(c));
ans=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i][j]==1)
c[j]++;
else
c[j]=0;
}
rear=0;
s[rear]=c[1];
l[rear++]=1;
for(int k=2;k<=m;k++)
{
if(c[k]>s[rear-1])
{s[rear]=c[k];l[rear++]=1;}
else
{
int num=0;
while(c[k]<=s[rear-1])
{
num+=l[rear-1];
ans=max(ans,num*s[rear-1]);
rear--;
if(rear==0)
break;
}
s[rear]=c[k];
l[rear++]=num+1;
}
}
int num=0;
while(rear>0)
{
num+=l[rear-1];
ans=max(ans,num*s[rear-1]);
rear--;
} }
printf("%d\n",ans*3);
}
return 0;
}



哇塞,果然只要360ms。算法是多么神奇和巧妙,效率的差距也是立竿见影

其实这道题目并不难,用O(n^2)效率的算法足可以Ac掉三个OJ里的题目,但是我想做ACM,不应该AC了就满足了,你追求越高,要求越高,你的境界就越高。仔细钻研一个问题,真是很重要的事情。

POJ 1964&HDU 1505&HOJ 1644 City Game(最大0,1子矩阵和总结)的更多相关文章

  1. HDU 1505 City Game (hdu1506 dp二维加强版)

    F - City Game Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submi ...

  2. POJ 2104&HDU 2665 Kth number(主席树入门+离散化)

    K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 50247   Accepted: 17101 Ca ...

  3. poj 1251 poj 1258 hdu 1863 poj 1287 poj 2421 hdu 1233 最小生成树模板题

    poj 1251  && hdu 1301 Sample Input 9 //n 结点数A 2 B 12 I 25B 3 C 10 H 40 I 8C 2 D 18 G 55D 1 E ...

  4. Hdu 5352 MZL's City (多重匹配)

    题目链接: Hdu 5352 MZL's City 题目描述: 有n各节点,m个操作.刚开始的时候节点都是相互独立的,一共有三种操作: 1:把所有和x在一个连通块内的未重建过的点全部重建. 2:建立一 ...

  5. Eight POJ - 1077 HDU - 1043 八数码

    Eight POJ - 1077 HDU - 1043 八数码问题.用hash(康托展开)判重 bfs(TLE) #include<cstdio> #include<iostream ...

  6. HDU 4849 Wow! Such City!陕西邀请赛C(最短路)

    HDU 4849 Wow! Such City! 题目链接 题意:依照题目中的公式构造出临接矩阵后.求出1到2 - n最短路%M的最小值 思路:就依据题目中方法构造矩阵,然后写一个dijkstra,利 ...

  7. POJ 1177/HDU 1828 picture 线段树+离散化+扫描线 轮廓周长计算

    求n个图矩形放下来,有的重合有些重合一部分有些没重合,求最后总的不规则图型的轮廓长度. 我的做法是对x进行一遍扫描线,再对y做一遍同样的扫描线,相加即可.因为最后的轮廓必定是由不重合的线段长度组成的, ...

  8. 【POJ 1964】 City Game

    [题目链接] http://poj.org/problem?id=1964 [算法] 记f[i]表示第i行最多向上延伸的行数 然后,对于每一行,我们用单调栈计算出这一行向上延伸的最大矩形面积,取最大值 ...

  9. HDU 1505 City Game(01矩阵 dp)

    Problem Description Bob is a strategy game programming specialist. In his new city building game the ...

随机推荐

  1. js获取iframe里面的元素

    直接获取不行 var  win2 = document.querySelector('iframe[width = "1280" ]').contentWindow; var lo ...

  2. VS2017 Pro未能找到路径“……\bin\roslyn\csc.exe”的解决方案

    VS2017改用roslyn编译的,新的roslyn编译器,支持c# 6.0语法.它放到bin里面去是为了支持asp.net应用的动态编译. 它是通过nuget的包Microsoft.CodeDom. ...

  3. Synchronizing Threads and GUI in Delphi application

    Synchronizing Threads and GUI   See More About delphi multithreading tthread class user interface de ...

  4. Git 学习笔记--Eclipse Git 插件安装

    http://benjsicam.me/blog/how-to-setup-eclipse-git-plugin-egit-for-github-part-1-tutorial/ http://ben ...

  5. TCPdump指定时间或者指定大小进行循环抓取报文

    背景:我们用tcpdump工具循环抓取网卡上的报文,我们会遇到如下情况: 1. 抓取报文后隔指定的时间保存一次: 2. 抓取报文后达到指定的大小保存一次: 本文就这两种情况给出tcpdump的使用方法 ...

  6. 深入浅出MFC——MFC多线程程序设计(七)

    1. 从操作系统层面看线程——三个观念:模块(MDB).进程(PDB).线程(TDB) 2. “执行事实”发生在线程身上,而不在进程身上.也就是说,CPU调度单位是线程而非进程.调度器据以排序的,是每 ...

  7. linux下命令学习

    1 在linux中,./代表当前目录下 例如 创建一个文件夹123   mkdir ./123   ->当前目录下创建一个123文件夹 mkdir -p ./123/456  在当前目录下创建一 ...

  8. 《转载》Fiddler 抓包工具总结

    阅读目录 1. Fiddler 抓包简介 1). 字段说明 2). Statistics 请求的性能数据分析 3). Inspectors 查看数据内容 4). AutoResponder 允许拦截制 ...

  9. WP8.1学习系列(第二十四章)——Json解析

    .net已经集成了json解析,类名叫DataContractJsonSerializer DataContractJsonSerializer 类型公开以下成员. 构造函数     名称 说明 Da ...

  10. jstorm开发指南-写个简单的jstorm应用

    jstorm开发指南-写个简单的jstorm应用 发表于 2015-07-18   |   分类于 大数据   |   暂无评论 jstorm 是阿里巴巴开源的基于storm采用Java重写的一套分布 ...