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

先看一下题吧:

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. printFinal用法示例

    printFinal是一个基于jQuery的打印插件,支持打印预览,使用很简单,废话不多多说,直接上代码. <!DOCTYPE html PUBLIC "-//W3C//DTD XHT ...

  2. 移动web——bootstrap响应式工具

    基本介绍 1.利用媒体查询功能并使用这些工具类可以方便的针对不同设备展示或隐藏页面内容. 基本使用 <!DOCTYPE html> <html lang="zh-CN&qu ...

  3. CSS——行高

    浏览器默认文字大小:16px 行高:是基线与基线之间的距离 行高=文字高度+上下边距 一行文字行高和父元素高度一致的时候,垂直居中显示. <!DOCTYPE html> <html& ...

  4. JS——switch case

    语法: switch(n) { case 1: 执行代码块 1 break; case 2: 执行代码块 2 break; default: n 与 case 1 和 case 2 不同时执行的代码 ...

  5. php入门学习相关函数

      1.join(): 定义和用法 join() 函数返回由数组元素组合成的字符串. join() 函数是 implode() 函数的别名. 注释:join() 函数接受两种参数顺序.但是由于历史原因 ...

  6. 使用super实现类的继承

    查看一个类继承了哪些类可以用__bases__方法查看 class People:   def __init__(self,name,age,sex):  self.name=name self.ag ...

  7. ceph对接openstack环境

    环境准备: 保证openstack节点的hosts文件里有ceph集群的各个主机名,也要保证ceph集群节点有openstack节点的各个主机名 一.使用rbd方式提供存储如下数据: (1)image ...

  8. 第二节:numpy之数组切片、数据类型转换、随机数组

  9. python编程——断言

    基本语法 assert_stmt ::= "assert" expression ["," expression] assert 5 > 3 # 肯定是对 ...

  10. 实验十二 团队作业8:软件测试与Alpha冲刺 第三天

    项目 内容 这个作业属于哪个课程 老师链接 这个作业的要求在哪里 作业链接地址 团队名称 always run 作业学习目标 (1)掌握软件测试基础技术.(2)学习迭代式增量软件开发过程(Scrum) ...