Describe:注意是“两次及以上”而不是“两种及以上”!!
code:
#include<bits/stdc++.h>
using namespace std;
int k,m,n,ans;
int f[1005][1005],cnt[20],a[1005][1005];
inline int read(){
int ret=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') f=-f;ch=getchar();}
while (ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar();
return ret*f;
}
inline int lowbit(int x){
return (-x)&x;
}
inline void write(int x){
if(x<0){putchar('-');write(-x);return;}
if(x/10)write(x/10);
putchar(x%10+'0');
}
inline int search(int x,int y){
if(x==n&&y==m+1)return 1; //Finish the search
if(y==m+1)y=1,x++; //下一行
int Sum=f[x-1][y]|f[x][y-1],pr=-1,sum=0,ans=0; //Sum=当前方格上面及左边共被使用多少个颜色
for(int i=Sum;i>0;i-=lowbit(i))sum++; //统计当前状态下有多少个颜色已被使用
if(n+m-x-y-1>k-sum)return 0; //剪枝,若剩余方格少于剩余颜色
for(int i=1;i<=k;i++){ //枚举状态
if((1<<(i-1))&Sum)continue; //已被使用
if(!a[x][y]||a[x][y]==i){ //未被涂色或已涂颜色未被使用
f[x][y]=Sum|(1<<(i-1)); //涂成当前颜色,加入状态
if(!cnt[i]){ //------------DFS模板---------------
cnt[i]++;
if(pr==-1)pr=search(x,y+1);
ans+=pr;
}
else cnt[i]++,ans+=search(x,y+1);
ans%=1000000007;cnt[i]--;
}
}
return ans;
}
int main(){
freopen("paths.in","r",stdin);
freopen("paths.out","w",stdout);
n=read(),m=read(),k=read();
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)a[i][j]=read(),cnt[a[i][j]]++;
ans=search(1,1);write(ans);
}