矩阵

来源:互联网 发布:unity3d 汽车模型 编辑:程序博客网 时间:2024/06/05 08:30

题目大意

求出一个n*m的矩阵中长至少为x宽至少为y的矩形价值的第K小。
每个元素都是非负整数,一个矩形的价值定义为所有元素和,相同价值的不同矩形在计算答案时算多个。

经典套路

观察一个以(x1,y1)为左上角的矩形。
假如右下角为(x2,y2),这个矩形一定比(x1,y1,x2+1,y2)和(x1,y1,x2,y2+1)都小。
所以先把所有位置为左上角的长为x宽为y的矩形扔进堆里。
每次取出一个矩形,然后将其往下和往右拓展一格的矩形扔进堆里。
我们这样可能拓展到同样的矩形,因此用map判重。
做k次即可。

#include<cstdio>#include<algorithm>#include<map>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;typedef long long ll;typedef pair<int,int> pi;typedef pair<pi,pi> pii;const int maxn=1000+10,maxtot=2000000+10;struct dong{    int x1,y1,x2,y2;    ll data;    friend bool operator <(dong a,dong b){        return a.data<b.data;    }};map<pii,bool> bz;ll sum[maxn][maxn],a[maxn][maxn],cnt;dong heap[maxtot],zlt;int i,j,k,l,t,n,m,x,y,x1,y1,x2,y2,p,tot;ll getsum(int x1,int y1,int x2,int y2){    return sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1];}void put(dong x){    heap[++tot]=x;    int i=tot;    while (i>1&&heap[i]<heap[i/2]){        swap(heap[i],heap[i/2]);        i/=2;    }}void deletemin(){    heap[1]=heap[tot];    tot--;    int i=1,j;    while (i*2<=tot){        if (i*2+1>tot||heap[i*2]<heap[i*2+1]) j=i*2;else j=i*2+1;        if (heap[j]<heap[i]){            swap(heap[i],heap[j]);            i=j;        }        else break;    }}bool pd(){    int i,j,k,l;    cnt=0;    fo(i,1,n-x+1)        fo(j,1,m-y+1)            fo(k,x,n-i+1)                fo(l,y,m-j+1){                    cnt++;                    if (cnt==p) return 1;                }    return 0;}bool dp(int x1,int y1,int x2,int y2){    if (bz[make_pair(make_pair(x1,y1),make_pair(x2,y2))]) return 1;    bz[make_pair(make_pair(x1,y1),make_pair(x2,y2))]=1;}int main(){    scanf("%d%d%d%d%d",&n,&m,&x,&y,&p);    fo(i,1,n)        fo(j,1,m)            scanf("%lld",&a[i][j]);    fo(i,1,n)        fo(j,1,m)            sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];    if (!pd()){        printf("-1\n");        return 0;    }    fo(i,1,n-x+1)        fo(j,1,m-y+1){            zlt.x1=i;            zlt.y1=j;            zlt.x2=i+x-1;            zlt.y2=j+y-1;            bz[make_pair(make_pair(x1,y1),make_pair(x2,y2))]=1;            zlt.data=getsum(i,j,i+x-1,j+y-1);            put(zlt);        }    p--;    while (p--){        zlt=heap[1];        deletemin();        x1=zlt.x1;y1=zlt.y1;        x2=zlt.x2;y2=zlt.y2;        if (x2<n&&!dp(x1,y1,x2+1,y2)){            zlt.x2++;            zlt.data=getsum(x1,y1,x2+1,y2);            put(zlt);            zlt.x2--;        }        if (y2<m&&!dp(x1,y1,x2,y2+1)){            zlt.y2++;            zlt.data=getsum(x1,y1,x2,y2+1);            put(zlt);        }    }    zlt=heap[1];    printf("%lld\n",zlt.data);}
0 0
原创粉丝点击