题目描述
有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小。
输入输出格式
输入格式:
第一行为3个整数,分别表示a,b,n的值
第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每行相邻两数之间用一空格分隔。
输出格式:
仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值。
思路:
本来想码二维线段树,懒了一发,写了个随机化,然后过了???
随机化很简单,每次随机一个点作为端点,
n很小,所以每次求差值的时间为最多为n^2=100
加上两个剪枝,已经跑过的点不再跑
当前位置的差值已经大于已有差值的也跳出
(记得加读优!!)
代码:
// luogu-judger-enable-o2 #include<iostream> #include<cstdio> #include<cstdlib> #include<ctime> #define rii register int i #define rij register int j #define rik register int k #define inf 1<<30 using namespace std; int a,b,n,x[1005][1005],bj[1005][1005]; inline int rd() { char ch = getchar(); int x = 0, f = 1; while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); } while('0' <= ch && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x * f; } int main() { a=rd(),b=rd(),n=rd(); for(rii=1;i<=a;i++) { for(rij=1;j<=b;j++) { x[i][j]=rd(); } } long long kkksc03=time(0); srand(kkksc03); int li=a-n+1; int lk=b-n+1; int ans=inf; for(rii=1;i<=350000;i++) { int ltt=rand()%li; ltt++; int kkk=rand()%lk; kkk++; if(bj[ltt][kkk]==1) { continue; } bj[ltt][kkk]=1; int maxn=0; int minx=inf; int pd=0; for(rij=ltt;j<=ltt+n-1;j++) { for(rik=kkk;k<=kkk+n-1;k++) { if(maxn<x[j][k]) { maxn=x[j][k]; } if(minx>x[j][k]) { minx=x[j][k]; } if(maxn-minx>=ans) { pd=1; break; } } if(pd==1) { break; } } if(ans>maxn-minx) { ans=maxn-minx; } } cout<<ans; }