BZOJ 5010: [Fjoi2017]矩阵填数
离散化
状压DP,一不小心就T了.......
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int mod=1e9+7; int h,w,m,n,Ex[1005],Ey[1005],Lim[1005],F[2005],cntx,cnty,cnt,Num[1005],belong[2005]; struct node{ int x1,y1,x2,y2,lim; }a[15]; int pow(int a,int b){ int ans=1; while (b){ if (b&1) ans=1ll*ans*a%mod; a=1ll*a*a%mod; b=b>>1; } return ans; } void Pre(){ sort(Ex+1,Ex+cntx+1); cntx=unique(Ex+1,Ex+cntx+1)-Ex-1; sort(Ey+1,Ey+cnty+1); cnty=unique(Ey+1,Ey+cnty+1)-Ey-1; cnt=0; for (int i=2; i<=cntx; i++) for (int j=2; j<=cnty; j++){ Num[++cnt]=(Ex[i]-Ex[i-1])*(Ey[j]-Ey[j-1]); Lim[cnt]=m; belong[cnt]=0; for (int k=0; k<n; k++) if (a[k].x1<=Ex[i-1] && a[k].x2>=Ex[i] && a[k].y1<=Ey[j-1] && a[k].y2>=Ey[j]) Lim[cnt]=min(Lim[cnt],a[k].lim); for (int k=0; k<n; k++) if (a[k].x1<=Ex[i-1] && a[k].x2>=Ex[i] && a[k].y1<=Ey[j-1] && a[k].y2>=Ey[j] && Lim[cnt]==a[k].lim) belong[cnt]|=(1<<k); } } int main(){ int T; scanf("%d",&T); while (T--){ scanf("%d%d%d%d",&h,&w,&m,&n); cntx=cnty=0; Ex[++cntx]=0; Ex[++cntx]=h; Ey[++cnty]=0; Ey[++cnty]=w; for (int i=0; i<n; i++){ scanf("%d%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2,&a[i].lim); a[i].x1--,a[i].y1--; Ex[++cntx]=a[i].x1; Ex[++cntx]=a[i].x2; Ey[++cnty]=a[i].y1; Ey[++cnty]=a[i].y2; } Pre(); memset(F,0,sizeof(F)); F[0]=1; for (int i=1; i<=cnt; i++) for (int now=(1<<n)-1; now>=0; now--) if (F[now]){ int Val=F[now]; F[now]=0; (F[now|belong[i]]+=1ll*Val*(pow(Lim[i],Num[i])-pow(Lim[i]-1,Num[i])+mod)%mod)%=mod; (F[now]+=1ll*Val*pow(Lim[i]-1,Num[i])%mod)%=mod; } printf("%d\n",F[(1<<n)-1]); } return 0; }