n,m<=1000是在逗你玩。。。
因为n+m-1>k无解啦。。。k<=10。。。
暴力大法好。。。
我们从左上向右下枚举棋子,遵循每次只放放过的棋子或者没放过的编号最小的棋子(当然是符合题目要求的情况下),最后用组合计数搞一搞即可以啦
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; #define two(x) (1<<(x)) const int Mod=(1e9)+7; int C[15][15],p[15][15],a[15][15],jc[15]; int ans,n,m,k,tot,cnt,i,j,k1,k2,c[100]; bool Judge(int x,int y,int c){ for (int i=x;i<=n;i++) for (int j=y;j<=m;j++) if (x!=i || y!=j){ if (a[i][j]==c) return 0; if ( ( p[i][j]|two(c-1) ) == ( two(k)-1 ) ) return 0; } return 1; } void dfs(int x,int y){ if (cnt>k) return; if (x>n){ ans=( ans+(LL)C[k-tot][cnt-tot]*jc[cnt-tot]%Mod )%Mod; return; } if (a[x][y]){ dfs(x+y/m,y%m+1); return; } for (int c=1;c<=cnt;c++) if ( !(p[x][y]&two(c-1)) && Judge(x,y,c) ){ for (int i=x;i<=n;i++) for (int j=y;j<=m;j++) p[i][j]|=two(c-1); dfs(x+y/m,y%m+1); for (int i=x;i<=n;i++) for (int j=y;j<=m;j++){ p[i][j]=p[i-1][j]|p[i][j-1]; if (a[i-1][j]) p[i][j]|=two(a[i-1][j]-1); if (a[i][j-1]) p[i][j]|=two(a[i][j-1]-1); } } cnt++; for (int i=x;i<=n;i++) for (int j=y;j<=m;j++) p[i][j]|=two(cnt-1); dfs(x+y/m,y%m+1); for (int i=x;i<=n;i++) for (int j=y;j<=m;j++){ p[i][j]=p[i-1][j]|p[i][j-1]; if (a[i-1][j]) p[i][j]|=two(a[i-1][j]-1); if (a[i][j-1]) p[i][j]|=two(a[i][j-1]-1); } cnt--; } int main(){ freopen("293B.in","r",stdin); freopen("293B.out","w",stdout); scanf("%d%d%d",&n,&m,&k); if (n+m-1>k){ printf("0\n",ans); return 0; } for (i=1;i<=n;i++) for (j=1;j<=m;j++){ scanf("%d",&a[i][j]); if (a[i][j]!=0) c[++tot]=a[i][j]; } sort(c+1,c+tot+1); cnt=tot=unique(c+1,c+tot+1)-c-1; for (i=1;i<=n;i++) for (j=1;j<=m;j++) if (a[i][j]) a[i][j]=lower_bound(c+1,c+tot+1,a[i][j])-c; for (i=1;i<=n;i++) for (j=1;j<=m;j++) if (a[i][j]) for (k1=i;k1<=n;k1++) for (k2=j;k2<=m;k2++) if (k1!=i || k2!=j) p[k1][k2]|=two(a[i][j]-1); for (i=1;i<=n;i++) for (j=1;j<=m;j++) if (a[i][j] && (p[i][j]&two(a[i][j]-1)) ) { puts("0"); return 0; } for (i=0;i<=10;i++) C[i][0]=1; for (i=1;i<=10;i++) for (j=1;j<=i;j++) C[i][j]=(C[i-1][j-1]+C[i-1][j])%Mod; for (i=1,jc[0]=1;i<=10;i++) jc[i]=((LL)jc[i-1]*i)%Mod; dfs(1,1); printf("%d\n",ans); return 0; }