BZOJ4118 : [Wf2015]Window Manager
OPEN、CLOSE、RESIZE操作直接模拟即可。
对于MOVE,设$f_i$表示$i$号矩形的坐标,先无视边界通过DP求出每个矩形的坐标,再根据边界反向用第二次DP求出被移动矩形移动的真实距离,再正着进行一次DP即可。
时间复杂度$O(n^3)$。
#include<cstdio> #include<algorithm> #define N 260 #define rep(i) for(int i=1;i<=n;i++) using namespace std; int xm,ym,n,remain,cnt,x,y,w,h,dx,dy,p,f[N],v[N];char op[9]; struct P{ int x,y,w,h;bool ex; P(){} P(int _x,int _y,int _w,int _h){x=_x,y=_y,w=_w,h=_h,ex=1;} }a[N]; inline bool between(int a,int b,int c){return a<=c&&c<=b;} inline bool cross(int a,int b,int c,int d){ if(d<a||c>b)return 0; return 1; } inline int getid(int x,int y){ rep(i)if(a[i].ex&&between(a[i].x,a[i].x+a[i].w-1,x)&&between(a[i].y,a[i].y+a[i].h-1,y))return i; return 0; } inline int Open(int x,int y,int w,int h){ if(x+w>xm||y+h>ym)return 0; rep(i)if(a[i].ex&&cross(a[i].x,a[i].x+a[i].w-1,x,x+w-1)&&cross(a[i].y,a[i].y+a[i].h-1,y,y+h-1))return 0; a[++n]=P(x,y,w,h); remain++; return 1; } inline void Close(int p){ a[p].ex=0; remain--; } inline int Resize(int p,int w,int h){ int x=a[p].x,y=a[p].y; if(x+w>xm||y+h>ym)return 0; rep(i)if(i!=p&&a[i].ex&&cross(a[i].x,a[i].x+a[i].w-1,x,x+w-1)&&cross(a[i].y,a[i].y+a[i].h-1,y,y+h-1))return 0; a[p].w=w,a[p].h=h; return 1; } int dfs11(int x){ if(v[x])return f[x]; v[x]=1; rep(i)if(a[i].ex&&cross(a[i].y,a[i].y+a[i].h-1,a[x].y,a[x].y+a[x].h-1)&&a[i].x<a[x].x)f[x]=max(f[x],dfs11(i)+a[i].w); return f[x]; } int dfs12(int x){ if(!v[x])return f[x]; v[x]=0; f[x]=min(f[x],xm-a[x].w); rep(i)if(a[i].ex&&cross(a[i].y,a[i].y+a[i].h-1,a[x].y,a[x].y+a[x].h-1)&&a[i].x>a[x].x)f[x]=min(f[x],dfs12(i)-a[x].w); return f[x]; } int dfs21(int x){ if(v[x])return f[x]; v[x]=1; rep(i)if(a[i].ex&&cross(a[i].y,a[i].y+a[i].h-1,a[x].y,a[x].y+a[x].h-1)&&a[i].x>a[x].x)f[x]=min(f[x],dfs21(i)-a[x].w); return f[x]; } int dfs22(int x){ if(!v[x])return f[x]; v[x]=0; f[x]=max(f[x],0); rep(i)if(a[i].ex&&cross(a[i].y,a[i].y+a[i].h-1,a[x].y,a[x].y+a[x].h-1)&&a[i].x<a[x].x)f[x]=max(f[x],dfs22(i)+a[i].w); return f[x]; } int dfs31(int x){ if(v[x])return f[x]; v[x]=1; rep(i)if(a[i].ex&&cross(a[i].x,a[i].x+a[i].w-1,a[x].x,a[x].x+a[x].w-1)&&a[i].y<a[x].y)f[x]=max(f[x],dfs31(i)+a[i].h); return f[x]; } int dfs32(int x){ if(!v[x])return f[x]; v[x]=0; f[x]=min(f[x],ym-a[x].h); rep(i)if(a[i].ex&&cross(a[i].x,a[i].x+a[i].w-1,a[x].x,a[x].x+a[x].w-1)&&a[i].y>a[x].y)f[x]=min(f[x],dfs32(i)-a[x].h); return f[x]; } int dfs41(int x){ if(v[x])return f[x]; v[x]=1; rep(i)if(a[i].ex&&cross(a[i].x,a[i].x+a[i].w-1,a[x].x,a[x].x+a[x].w-1)&&a[i].y>a[x].y)f[x]=min(f[x],dfs41(i)-a[x].h); return f[x]; } int dfs42(int x){ if(!v[x])return f[x]; v[x]=0; f[x]=max(f[x],0); rep(i)if(a[i].ex&&cross(a[i].x,a[i].x+a[i].w-1,a[x].x,a[x].x+a[x].w-1)&&a[i].y<a[x].y)f[x]=max(f[x],dfs42(i)+a[i].h); return f[x]; } inline int Move(int p,int dx,int dy){ if(dx+dy==0)return 0; int x=a[p].x,y=a[p].y,t; if(dx>0){ rep(i)v[i]=0,f[i]=a[i].x; f[p]+=dx; rep(i)if(a[i].ex)dfs11(i); t=dfs12(p); rep(i)v[i]=0,f[i]=a[i].x; f[p]=t; rep(i)if(a[i].ex)dfs11(i); rep(i)if(a[i].ex)a[i].x=f[i]; return f[p]-x; }else if(dx<0){ rep(i)v[i]=0,f[i]=a[i].x; f[p]+=dx; rep(i)if(a[i].ex)dfs21(i); t=dfs22(p); rep(i)v[i]=0,f[i]=a[i].x; f[p]=t; rep(i)if(a[i].ex)dfs21(i); rep(i)if(a[i].ex)a[i].x=f[i]; return f[p]-x; }else if(dy>0){ rep(i)v[i]=0,f[i]=a[i].y; f[p]+=dy; rep(i)if(a[i].ex)dfs31(i); t=dfs32(p); rep(i)v[i]=0,f[i]=a[i].y; f[p]=t; rep(i)if(a[i].ex)dfs31(i); rep(i)if(a[i].ex)a[i].y=f[i]; return f[p]-y; }else{ rep(i)v[i]=0,f[i]=a[i].y; f[p]+=dy; rep(i)if(a[i].ex)dfs41(i); t=dfs42(p); rep(i)v[i]=0,f[i]=a[i].y; f[p]=t; rep(i)if(a[i].ex)dfs41(i); rep(i)if(a[i].ex)a[i].y=f[i]; return f[p]-y; } return 0; } inline int abs(int x){return x>0?x:-x;} int main(){ scanf("%d%d",&xm,&ym); while(~scanf("%s%d%d",op,&x,&y)){ cnt++; if(op[0]=='O'){ scanf("%d%d",&w,&h); if(!Open(x,y,w,h))printf("Command %d: OPEN - window does not fit\n",cnt); } if(op[0]=='C'){ p=getid(x,y); if(!p)printf("Command %d: CLOSE - no window at given position\n",cnt); else Close(p); } if(op[0]=='R'){ scanf("%d%d",&w,&h); p=getid(x,y); if(!p)printf("Command %d: RESIZE - no window at given position\n",cnt); else if(!Resize(p,w,h))printf("Command %d: RESIZE - window does not fit\n",cnt); } if(op[0]=='M'){ scanf("%d%d",&dx,&dy); p=getid(x,y); if(!p)printf("Command %d: MOVE - no window at given position\n",cnt); else{ p=Move(p,dx,dy); if(abs(p)!=abs(dx+dy))printf("Command %d: MOVE - moved %d instead of %d\n",cnt,abs(p),abs(dx+dy)); } } } printf("%d window(s):\n",remain); rep(i)if(a[i].ex)printf("%d %d %d %d\n",a[i].x,a[i].y,a[i].w,a[i].h); return 0; }