題解 【POI2008】KUP-Plot purchase
阿新 • • 發佈:2019-03-28
部分 ase 矩形區域 else get for bit 題目 .org ,
題面
先把題目意思講一下吧:
給一個 \(n*n\) 的地圖,每個格子有一個價格,找一個矩形區域,使其價格總和位於\([k,2k]\).
那麽首先,可以想到,如果\(a[i][j]\)(格子的價格,下同)位於\([k,2k]\),直接輸出就好.
而對於\(a[i][j]\)>\(2k\)的格子,它是不可能被選的,那麽可以把它視為障礙物,
然後,剩下的格子的價格就一定小於\(k\).
那麽,根據懸線法,
如果我們找到了一個極大子矩陣,且矩陣和(設為\(sum\))>=\(k\)(小於肯定是不行的),
如果\(sum\)<=\(2k\),就直接輸出答案,
否則,判斷第一行的和\(sum_{1}\)
若\(sum_{1}\)>=\(k\),那在第一行中肯定有解,
因為每個元素都小於\(k\)(前面說過了),
那麽不存在一個格子能使矩陣和從大於\(2k\)一下變到小於\(k\),
因此只需要一個個刪掉第一行的元素,直到符合要求即可.
而當\(sum_{1}\)<\(k\)時,
因為\(sum\)>\(2k\),
所以可以刪掉第一行,再繼續判斷剩下的矩陣.
這一部分的實現方式:
inline void print_t(int x1,int y1,int x2,int y2)/*以(x1,y1)為左上角,(x2,y2)為右下角*/{ while(sum(x1,y1,x2,y2)/*矩陣和*/>m*2){ if(x1==x2) y2--; else if(sum(x1,y1,x1,y2)>=m) x2=x1; else x1++; } printf("%d %d %d %d\n",y1,x1,y2,x2); exit(0);//終止程序 }
最後註意:找到答案後直接終止程序!
上完整代碼:
#include<bits/stdc++.h> #define ll long long using namespace std; inline int read(){ int sum=0,f=1;char ch=getchar(); while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0' && ch<='9'){sum=sum*10+ch-'0';ch=getchar();} return f*sum; } int n,m; ll a[2001][2001];//價格 ll s[2001][2001];//二維前綴和 int h[2001][2001]/*懸線*/,l[2001][2001]/*向左展開的位置*/,r[2001][2001]/*向右展開的位置*/; inline ll sum(int x1,int y1,int x2,int y2)/*矩陣和*/{ return s[x2][y2]+s[x1-1][y1-1]-s[x1-1][y2]-s[x2][y1-1]; } inline void print_t(int x1,int y1,int x2,int y2){ while(sum(x1,y1,x2,y2)>m*2){ if(x1==x2) y2--; else if(sum(x1,y1,x1,y2)>=m) x2=x1; else x1++; } printf("%d %d %d %d\n",y1,x1,y2,x2); exit(0); } int main(){ // freopen("kup.in","r",stdin); // freopen("kup.out","w",stdout); m=read();n=read();//m就是k,只是看上去順眼一些而已[滑稽] for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){ a[i][j]=read(); s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j]; if(a[i][j]<m||a[i][j]>2*m) continue; printf("%d %d %d %d\n",j,i,j,i); return 0; } for(int i=1;i<=n;i++) r[0][i]=n+1; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) h[i][j]= a[i][j]>2*m? 0:h[i-1][j]+1; for(int i=1;i<=n;i++){ int ret=0; for(int j=1;j<=n;j++){ if(h[i][j]) l[i][j]=max(l[i-1][j],ret); else ret=j,l[i][j]=0; } ret=n+1; for(int j=n;j;j--){ if(h[i][j]) r[i][j]=min(r[i-1][j],ret); else ret=j,r[i][j]=n+1; } } for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(!h[i][j]) continue; int x1=i-h[i][j]+1; int y1=l[i][j]+1,y2=r[i][j]-1; if(sum(x1,y1,i,y2)<m) continue; print_t(x1,y1,i,y2); } } puts("NIE"); return 0; }
題解 【POI2008】KUP-Plot purchase