题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1127
大于2*K的视为不能选的“坏点”。有单个格子满足的就直接输出。
剩下的都是<K的格子,求面积大于等于K的一个矩形;若还<=2*K就直接输出,否则一列一列删;
删去一列后若仍>=2*K,继续;若>=K&&<=2*K,就输出;若<K,则删去的那一列满足>=K,在那列上一格一格删,因为格子<K,所以不能从>2*K跳到<K,一定有解了。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const int N=2005; int n,K,D,a[N][N],l[N][N],r[N][N],u[N][N],p0,p1; ll s[N][N]; bool b[N][N],flag; int rdn() { int ret=0;bool fx=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();} while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar(); return fx?ret:-ret; } ll calc(int h1,int l1,int h2,int l2) { return s[h2][l2]-s[h2][l1-1]-s[h1-1][l2]+s[h1-1][l1-1]; } void solve2(int h1,int h2,int j) { int sm=calc(h1,j,h2,j); if(sm>=K&&sm<=D){printf("%d %d %d %d ",j,h1,j,h2);return;} for(int i=h2;i>=h1;i--) { sm-=a[i][j]; if(sm>=K&&sm<=D){printf("%d %d %d %d ",j,h1,j,i-1);return;} } } void solve(int h1,int l1,int h2,int l2) { ll sm=calc(h1,l1,h2,l2); if(sm<K)return; if(sm>=K&&sm<=D){printf("%d %d %d %d ",l1,h1,l2,h2);flag=1;return;} for(int i=l2;i>=l1;i--) { sm=calc(h1,l1,h2,i-1); if(sm>=K&&sm<=D) { printf("%d %d %d %d ",l1,h1,i-1,h2); flag=1;return; } if(sm<K) { solve2(h1,h2,i);flag=1;return; } } } int main() { K=rdn(); n=rdn(); D=(K<<1); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { a[i][j]=rdn(); if(a[i][j]>D)b[i][j]=1; if(a[i][j]>=K&&a[i][j]<=D)p0=j,p1=i; s[i][j]=s[i][j-1]+a[i][j]; } if(p0){printf("%d %d %d %d ",p0,p1,p0,p1);return 0;} for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)s[i][j]+=s[i-1][j]; for(int i=1,k;i<=n;i++) for(int j=1,k=1;j<=n;j++) { if(!b[i-1][j]) u[i][j]=u[i-1][j]+1; else u[i][j]=1; if(!b[i][j])l[i][j]=max(k,l[i-1][j]); else k=j+1; } for(int j=1;j<=n;j++)r[0][j]=n;//! for(int i=1,k;i<=n;i++) for(int j=n,k=n;j>=1;j--) { if(!b[i][j])r[i][j]=min(k,r[i-1][j]); else k=j-1,r[i][j]=n;//for don't influence i+1,j if(!b[i][j])solve(i-u[i][j]+1,l[i][j],i,r[i][j]); if(flag)return 0; } puts("NIE"); return 0; }