https://vjudge.net/problem/UVALive-3029

题意:

给出一个只含有F和R字母的矩阵,求出全部为F的面积最大的矩阵并且输出它的面积乘以3。

思路:

求面积最大的子矩阵,可以用扫描线。参考训练指南(orz,虽然并不知道为什么用扫描线)。

对于每一个格子包含F,我们可以把它向上拉成一条悬线,直到上面的格子为R,然后观察这条悬线可以扫到左边与右边的最大距离,那么我们所求的面积就是所有的悬线中 悬线的长度乘以(右边界 - 左边界 + 1)的最大值。

然后,需要计算悬线的长度,用up来表示,那么当这个格子为F时up(i,j) = up(i - 1,j) + 1(i >= 1),up(i,j) = 1,(i == 0);

当这个格子为R时,up(i,j) = 0。

然后,用left数组和right数组维护左右边界的信息:

我们假设lo是当前格子之前的最近的是R的格子,从左往右遍历,那么 lo 的初值是-1,那么当(i,j) 为 F时 ,left(i,j) = max(left(i-1,j),lo + 1),为什么呢,因为当前的悬线如果是包含上一行此列的格子的话,那么就要考虑上一行左边的情况了;

当(i,j)为R时,left(i,j) = 0。

维护右边界的信息同理,不同的是求最小值和从右往左遍历。

!!!:记住一边遍历,一边维护。输入也是坑!

代码:

 #include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std; char a[][];
int up[][],right[][],left[][]; int main()
{
int t; scanf("%d",&t); while(t--)
{
int m,n; memset(a,,sizeof(a));
memset(up,,sizeof(up));
memset(right,,sizeof(right));
memset(left,,sizeof(left)); scanf("%d%d",&m,&n); getchar(); for (int i = ;i < m;i++)
for (int j = ;j < n;j++)
{
char s; s = getchar(); while (s != 'R' && s != 'F') s = getchar(); if (s == 'R') a[i][j] = ;
else a[i][j] = ;
} /*for (int i= 0;i < m;i++)
{
for (int j = 0;j < n;j++) printf("%d",(int)a[i][j]); printf("\n");
}*/ int ans = ; for (int i = ;i < m;i++)
{
for (int j = ;j < n;j++)
{
if (i == )
{
up[i][j] = a[i][j];
}
else
{
if (a[i][j]) up[i][j] = up[i-][j] + ;
else up[i][j] = ;
}
} int lo = -,ro = n; if (i == )
{
for (int j = ;j < n;j++)
{
if (a[i][j] == ) left[i][j] = , lo = j;
else left[i][j] = lo + ;
} for (int j = n - ;j >= ;j--)
{
if (a[i][j] == ) right[i][j] = n, ro = j;
else right[i][j] = ro - ;
} for (int j = ;j < n;j++)
{
int tmp = up[i][j] * (right[i][j] - left[i][j] + ); ans = max(ans,tmp * );
}
}
else
{
for (int j = ;j < n;j++)
{
if (a[i][j] == ) left[i][j] = , lo = j;
else left[i][j] = max(lo + ,left[i-][j]);
} for (int j = n - ;j >= ;j--)
{
if (a[i][j] == ) right[i][j] = n, ro = j;
else right[i][j] = min(ro - ,right[i-][j]);
} for (int j = ;j < n;j++)
{
int tmp = up[i][j] * (right[i][j] - left[i][j] + ); ans = max(ans,tmp * );
}
}
} /*for (int i = 0;i < m;i++)
{
for (int j = 0;j < n;j++)
{
printf("%d %d %d\n",up[i][j],left[i][j],right[i][j]);
}
}*/ printf("%d\n",ans);
} return ;
}

uvalive 3029 City Game的更多相关文章

  1. 【UVALive】3029 City Game(悬线法)

    题目 传送门:QWQ 分析 以前见到过差不多的这题. xhk说是单调栈水题,但我又不会单调栈,于是当时就放下了. 这么久过去了我还是不会用单调栈做这题,用的是悬线法. 非常好写 代码 #include ...

  2. City Game UVALive - 3029(悬线法求最大子矩阵)

    题意:多组数据(国外题好像都这样),每次n*m矩形,F表示空地,R表示障碍 求最大子矩阵(悬线法模板) 把每个格子向上延伸的空格看做一条悬线 以le[i][j],re[i][j],up[i][j]分别 ...

  3. UVALive 6889 City Park 并查集

    City Park 题目连接: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=122283#problem/F Description P ...

  4. 并查集 - UVALive 6889 City Park

    City Park Problem's Link: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=129725 Mean: 在 ...

  5. LA 3029 City Game

    LA 3029 求最大子矩阵问题,主要考虑枚举方法,直接枚举肯定是不行的,因为一个大矩阵的子矩阵个数是指数级的,因此应该考虑先进行枚举前的扫描工作. 使用left,right,up数组分别记录从i,j ...

  6. LA 3029 - City Game (简单扫描线)

    题目链接 题意:给一个m*n的矩阵, 其中一些格子是空地(F), 其他是障碍(R).找一个全部由F 组成的面积最大的子矩阵, 输出其面积乘以3的结果. 思路:如果用枚举的方法,时间复杂度是O(m^2 ...

  7. UVa LA 3029 City Game 状态拆分,最大子矩阵O(n2) 难度:2

    题目 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_pr ...

  8. UVaLive 3695 City Game (扫描线)

    题意:给定m*n的矩阵,有的是空地有的是墙,找出一个面积最大的子矩阵. 析:如果暴力,一定会超时的.我们可以使用扫描线,up[i][j] 表示从(i, j)向上可以到达的最高高度,left[i][j] ...

  9. UVaLive 6854 City (暴力)

    题意:给定一个 n*m 的矩阵,表示有多少条道路与它相连,其中有一个-1,表示未知,道路只能横着和竖着,求-1处的值. 析:根据题意可知,一个点,与其他周围的四个点都可能相连的,也就是说肯定有共用道路 ...

随机推荐

  1. github开源项目学习-front-end-collect

    About 项目地址 项目预览demo(githubio加载较慢) 开源项目fork自:https://github.com/foru17/front-end-collect 此文章是对此开源项目使用 ...

  2. 浅述 Java 并发

    浅述 Java 并发 volatile volatile只能保证变量对各个线程的可见性,但不能保证原子性.关于 Java语言 volatile 的使用方法就不多说了,我的建议是 除了 配合packag ...

  3. jvm系列 (五) ---类的加载机制

    类的加载机制 目录 jvm系列(一):jvm内存区域与溢出 jvm系列(二):垃圾收集器与内存分配策略 jvm系列(三):锁的优化 jvm系列 (四) ---强.软.弱.虚引用 我的博客目录 什么是类 ...

  4. 猎八哥浅谈MYSQL触发器

    什么是MYSQL触发器,我们先了解一下触发的意思.触发的字面意思是指因触动而激发起某种反应. MYSQL必知必会中对触发器的解释是:MySQL响应以下任意语句而自动执行的一条MySQL语句(或位于 B ...

  5. 201521123091 《Java程序设计》第9周学习总结

    Java 第九周总结 第九周的作业. 目录 1.本章学习总结 2.Java Q&A 3.码云上代码提交记录及PTA实验总结 1.本章学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异 ...

  6. 《Java程序设计》第1周学习总结

    1.本周本章学习总结 感觉装环境和基础语言也没什么好总结的,就谈谈我对java的认识. 接触的语言也不多,c语言,python.去年科研立项立了个安卓开发的项.也有去学了一阶段java.由于种种原因没 ...

  7. Swing-setAlignmentX()用法-入门

    先看下API: public void setAlignmentX(float alignmentX) 设置垂直对齐方式. 参数: alignmentX - 新的垂直对齐方式 网上关于这个函数的详细情 ...

  8. 201521123065《java程序设计》第七周学习总结

    1. 本周学习总结 1.Iterator迭代器用于遍历集合中的元素: 2.使用迭代器删除元素一定要先指向下一个元素在删除第一个元素: 3.List可以有重复对象: Set不能有重复对象: 4.Map是 ...

  9. 201521123013 《Java程序设计》第3周学习总结

    1. 本章学习总结 2. 书面作业 Q1.代码阅读 public class Test1 { private int i = 1;//这行不能修改 private static int j = 2; ...

  10. 201521123073《Java程序设计》第2周学习总结

    1. 本周学习总结 1.学习了枚举类型的应用: 枚举也可以象一般的类一样添加方法和属性,你可以为它添加静态和非静态的属性或方法,这一切都象你在一般的类中做的那样. public enum Season ...