[HAOI2007]理想的正方形(随机化,骗分?)

题目描述

有一个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;
}

 

转载于:https://www.cnblogs.com/ztz11/p/9384327.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值