大家吸取我的教训,想好再写。我码了好长时间,最后发现算法处理的是另一个问题,我处理的是正方形情况的,才能用我优化之后的记忆化搜索,然而矩形就凉了。

先看一下题吧:

Description

  有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值
的差最小。
Input   第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每
行相邻两数之间用一空格分隔。
%的数据2<=a,b<=,n<=a,n<=b,n<=
Output   仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值。
Sample Input Sample Output HINT Source

我的反面教材代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(int i = a;i <= n;i++)
#define lv(i,a,n) for(int i = a;i >= n;i--)
#define clean(a) memset(a,0,sizeof(a))
const int INF = << ;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
char c;
bool op = ;
while(c = getchar(), c < '' || c > '')
if(c == '-') op = ;
x = c - '';
while(c = getchar(), c >= '' && c <= '')
x = x * + c - '';
if(op) x = -x;
}
template <class T>
void write(T x)
{
if(x < ) putchar('-'), x = -x;
if(x >= ) write(x / );
putchar('' + x % );
}
int a,b,n;
int p[][];
int f[][][][];
int l[];
void dfs(int o,int x1,int y1,int x2,int y2)
{
if(f[x1][y1][o][] != -)
return;
if(x1 == x2 && y1 == y2)
{
f[x1][y1][o][] = p[x1][y1];
f[x1][y1][o][] = p[x1][y1];
return;
}
int minn = INF;
int maxn = ;
dfs(o + ,x1,y1,x1 + l[o],y1 + l[o]);
dfs(o + ,a - l[o],y1,a,y1 + l[o]);
dfs(o + ,x1,b - l[o],x1 + l[o],b);
dfs(o + ,a - l[o],b - l[o],a,b);
// printf("%d %d %d %d\n",a - l[o],b - l[o],a,b);
maxn = max(maxn,f[x1][y1][o + ][]);
minn = min(minn,f[x1][y1][o + ][]);
maxn = max(maxn,f[a - l[o]][y1][o + ][]);
minn = min(minn,f[a - l[o]][y1][o + ][]);
maxn = max(maxn,f[x1][b - l[o]][o + ][]);
minn = min(minn,f[x1][b - l[]][o + ][]);
maxn = max(maxn,f[a - l[o]][b - l[o]][o + ][]);
minn = min(minn,f[a - l[o]][b - l[o]][o + ][]);
f[x1][y1][o][] = maxn;
f[x1][y1][o][] = minn;
return;
}
int main()
{
memset(f,-,sizeof(f));
read(a);read(b);read(n);
duke(i,,a)
{
duke(j,,b)
read(p[i][j]);
}
int k = n,len = ;
while(k > )
{
k = ceil(k / );
l[++len] = k;
// cout<<k<<endl;
}
duke(i,,a - n)
duke(j,,b - n)
dfs(,i,j,i + n,j + n);
printf("%d %d\n",f[][][][],f[][][][]);
return ;
}
/*
5 4 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2
*/

然后就凉了,懒得写了,用二维的RMQ搞一下,抄了个比较清晰的代码。。。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std; const int INF = ;
const int maxm = + ;
const int maxn = + ;
const int maxlog = ; int a, b, n;
int logn;
int grid[maxm][maxm];
int maxv[maxm][maxm], minv[maxm][maxm]; int query (int x, int y)
{
int _max = , _min = ;
_max = max(maxv[x][y], max(maxv[x+n-(<<logn)][y+n-(<<logn)], max(maxv[x+n-(<<logn)][y], maxv[x][y+n-(<<logn)])));
_min = min(minv[x][y], min(minv[x+n-(<<logn)][y+n-(<<logn)], min(minv[x+n-(<<logn)][y], minv[x][y+n-(<<logn)])));
return _max - _min;
} int main ()
{
// freopen("in.txt", "r", stdin);
cin >> a >> b >> n;
for (int i = ; i < a; i++)
for (int j = ; j < b; j++)
{
scanf("%d", &grid[i][j]);
maxv[i][j] = minv[i][j] = grid[i][j];
} for (logn = ; ((<<(logn+)) <= n); logn++);
for (int k = ; k < logn; k++)
for (int i = ; i+(<<k) < a; i++)
for (int j = ; j+(<<k) < b; j++)
{
maxv[i][j] = max(maxv[i][j], max(maxv[i+(<<k)][j+(<<k)], max(maxv[i+(<<k)][j], maxv[i][j+(<<k)])));
minv[i][j] = min(minv[i][j], min(minv[i+(<<k)][j+(<<k)], min(minv[i+(<<k)][j], minv[i][j+(<<k)])));
} int ans = INF;
for (int i = ; i <= a-n; i++)
for (int j = ; j <= b-n; j++)
ans = min(ans, query(i, j)); cout << ans;
return ;
}

唉,后悔啊。。。

B1047 理想的正方形 RMQ的更多相关文章

  1. [BZOJ1047][HAOI2007]理想的正方形(RMQ+DP)

    题意 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 思路 RMQ求 再DP 代码 #include<cstdio> #i ...

  2. 理想的正方形 HAOI2007(二维RMQ)

    理想的正方形 省队选拔赛河南  时间限制: 1 s  空间限制: 256000 KB  题目等级 : 大师 Master       题目描述 Description 有一个a*b的整数组成的矩阵,现 ...

  3. HAOI2007 理想的正方形

    1047: [HAOI2007]理想的正方形 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1402  Solved: 738[Submit][Sta ...

  4. RAM——[HAOI2007]理想的正方形

    题目:[HAOI2007]理想的正方形 描述: [问题描述] 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. [输入]: 第一行为3个 ...

  5. [Luogu 2216] [HAOI2007]理想的正方形

    [Luogu 2216] [HAOI2007]理想的正方形 题目描述 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入输出格式 输 ...

  6. P2216 [HAOI2007]理想的正方形 (单调队列)

    题目链接:P2216 [HAOI2007]理想的正方形 题目描述 有一个 \(a\times b\)的整数组成的矩阵,现请你从中找出一个 \(n\times n\)的正方形区域,使得该区域所有数中的最 ...

  7. BZOJ1047: [HAOI2007]理想的正方形 [单调队列]

    1047: [HAOI2007]理想的正方形 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2857  Solved: 1560[Submit][St ...

  8. 【bzoj1047】理想的正方形

    [bzoj1047]理想的正方形 题意 给定\(a*b\)由整数组成的矩形. 现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值 的差最小. \(1\leq a,b\leq 10 ...

  9. bzoj 1047 : [HAOI2007]理想的正方形 单调队列dp

    题目链接 1047: [HAOI2007]理想的正方形 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2369  Solved: 1266[Submi ...

随机推荐

  1. 11、scala函数式编程

    1.将函数赋值给变量 2.匿名函数 3.高阶函数 4.高阶函数的类型推断 5.Scala的常用高级函数 6.闭包 7.SAM转换 8.Currying函数 9.return 1.将函数赋值给变量 Sc ...

  2. crontab错误处理

    crontab任务跑着跑着突然停了,莫名奇妙,查看日志,发现以下错误: 网上搜了一下报错,提示说是调整打开最大进程数,设置如下

  3. 微服务的一种开源实现方式——dubbo+zookeeper

    转自: http://blog.csdn.NET/zhdd99/article/details/52263609 微服务架构成了当下的技术热点,实现微服务是要付出很大成本的,但也许是因为微服务的优点太 ...

  4. Android中Application类总结

    本文出处: 炎之铠csdn博客:http://blog.csdn.net/totond 炎之铠邮箱:yanzhikai_yjk@qq.com 本文原创,转载请注明本出处! 前言 最近的开发中经常使用到 ...

  5. Split()函数

    最近遇到一个有趣的问题关于使用Split函数 ,该函数能够根据传递的参数拆分,并返回一个string的数组. 贴出一个奇怪的例子 using System; using System.Collecti ...

  6. Photoshop如何实现图片相对画布居中

    先按ctrl+A,再选择要居中的图层,然后就会发现居中按钮被激活了

  7. CSS超链接常见四种状态在控制

    一.首选设置一下以下4种状态常: 1.a:active是超级链接的初始状态 2.a:hover是把鼠标放上去时的状况 3.a:link 是鼠标点击时 4.a:visited是访问过后的情况.

  8. MySQL操作数据库和表的基本语句(DDL

    1.创建数据库: CREATE DATABASE 数据库名; eg.CREATE DATABASE test_ddl;122.创建表 CREATE TABLE 表名(列名 数据类型 约束,...); ...

  9. mybatis批量操作(foreach)

    foreach可以在SQL语句中通过拼接的方式进行集合迭代.foreach元素的属性主要有collection,item,index,separator,open,close. item属性:表示循环 ...

  10. CentOS7搭建KMS服务器

    使用vlmcsd搭建KMS服务器 1.下载vlmcsd: wget https://github.com/Wind4/vlmcsd/releases/download/svn1111/binaries ...