考试 T2,没想到真的就是一个大爆搜啊~
搜索时几个剪枝:
1.剩余可用颜色要大于等于剩余步数
2.颜色从没用过的里找,然后用二进制状压存储.
code:
#include <bits/stdc++.h>
using namespace std;
void setIO(string s)
{
string in=s+".in";
string out=s+".out";
freopen(in.c_str(),"r",stdin);
// freopen(out.c_str(),"w",stdout);
}
const int mod=1e9+7;
int lg[1040],n,m,k,a[23][23],f[23][23],v[23];
int dfs(int x,int y)
{
if(y==m+1) ++x,y=1;
if(x==n+1) return 1;
int s=f[x-1][y]|f[x][y-1],calc=-1,ret=0;
int S=~s&((1<<k)-1);
if(n+m-x-y+1>lg[S]) return 0;
for(int tmp=0;tmp<k;++tmp)
{
if(S&(1<<tmp))
{
if(a[x][y]==0||a[x][y]==tmp+1)
{
v[tmp+1]++;
f[x][y]=s|(1<<tmp);
if(v[tmp+1]==1)
{
if(calc==-1) calc=dfs(x,y+1);
ret+=calc;
}
else ret+=dfs(x,y+1);
if(ret>=mod) ret-=mod;
v[tmp+1]--;
}
}
}
return ret;
}
int main()
{
// setIO("input");
int i,j;
for(i=1;i<1024;++i) lg[i]=lg[i>>1]+(i&1);
scanf("%d%d%d",&n,&m,&k);
if(n+m-1>k) { printf("0\n"); return 0; }
for(i=1;i<=n;++i)
{
for(j=1;j<=m;++j)
scanf("%d",&a[i][j]), v[a[i][j]]++;
}
printf("%d\n",dfs(1,1));
return 0;
}