ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

Description

定义和谐矩阵为长不小于 Mina 且宽不小于 Minb 的矩阵,矩阵的权值为整个矩阵内所有数的和。给定一个长为 N
,宽为 M 的矩阵 A,求它的所有和谐子矩阵中权值第 K 小的矩阵,并输出它的权值。

Input

第 1 行为五个正整数,分别为 N , M , Mina , Minb , K,相邻两个数用一个空格分隔。接下来的 N 行,每行 M
 个用一个空格分隔的数,表示给定的矩阵 A。
1 <= N,M <=1000, 1 <= Mina <= N, 1 <= Minb <= M,
1 <= K <= 250000 ,矩阵 A 内每个数均为不超过 3000 的非负整数

Output

仅一行,一个数,表示第 K 小矩阵的权值。如果第 K 小矩阵不存在,输出-1。

由于矩阵内整数非负,若子矩阵P包含子矩阵Q则sum(P)>sum(Q)

最小的子矩阵长宽一定为(Mina , Minb),从最小的矩阵开始向外bfs,每个子矩阵可以向上/下/左/右扩展一行/列,注意判重

用堆维护搜索顺序,散列表维护一个状态是否出现过,第k个出堆的子矩阵为答案

#include<cstdio>
#include<cstdlib>
#include<queue>
const int P=2097152,R=10000000;
char buf[R],*ptr=buf-1;
inline int _int(){
    int x=0,c=*++ptr;
    while(c<48)c=*++ptr;
    while(c>47)x=x*10+c-48,c=*++ptr;
    return x;
}
int n,m,n1,m1,k;
unsigned int s[1024][1024],rnd[1024][1024];
struct data{
    unsigned int x1,y1,x2,y2,sum;
    data(){}
    inline data(int _x1,int _y1,int _x2,int _y2):x1(_x1),y1(_y1),x2(_x2),y2(_y2){
        sum=s[x2][y2]+s[x1][y1]-s[x2][y1]-s[x1][y2];
    }
}w;
inline bool operator<(const data&a,const data&b){
    return a.sum>b.sum;
}
inline bool operator==(const data&a,const data&b){
    return a.x1==b.x1&&a.y1==b.y1&&a.y2==b.y2&&a.x2==b.x2;
}
std::priority_queue<data>q;
bool ins(data x){
    static data xs[P];
    static bool ed[P];
    int w=rnd[x.x1][x.y1]^rnd[x.x2][x.y2];
    while(ed[w]){
        if(xs[w]==x)return 0;
        w+=12347;
        if(w>=P)w-=P;
    }
    xs[w]=x;ed[w]=1;
    return 1;
}
inline void push(data x){
    if(ins(x))q.push(x);
}
int main(){
    fread(buf,1,R-4,stdin);
    srand(1844677);
    n=_int();m=_int();n1=_int();m1=_int();k=_int();
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)s[i][j]=_int()+s[i][j-1],rnd[i][j]=(rand()^rand()<<10)&2097151;
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)s[i][j]+=s[i-1][j];
    for(int i=n1;i<=n;i++)for(int j=m1;j<=m;j++)push(data(i-n1,j-m1,i,j));
    for(int i=0;i<k;i++){
        if(q.empty()){
            puts("-1");
            return 0;
        }
        w=q.top();q.pop();
        if(w.x1)push(data(w.x1-1,w.y1,w.x2,w.y2));
        if(w.y1)push(data(w.x1,w.y1-1,w.x2,w.y2));
        if(w.x2!=n)push(data(w.x1,w.y1,w.x2+1,w.y2));
        if(w.y2!=m)push(data(w.x1,w.y1,w.x2,w.y2+1));
    }
    printf("%u\n",w.sum);
    return 0;
}

 

posted on 2016-07-10 15:59  nul  阅读(349)  评论(0编辑  收藏  举报