一开始看错题意了,测试数据都理解不了,放了一段时间,今天再去看题才读懂,要求每天路径都满足条件才算一种情况,这样就直接dfs+剪枝,开一个二维数组记录状态压缩记录颜色。
ACcode:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int NS=1111;
const int MOD=1000000007;
int n,m,k;
int v[11],u[NS];
int s[NS][NS],a[NS][NS];
int one_num(int z)
{
int cnt=0;
for (;z>0;z=z&(z-1))
cnt++;
return cnt;
}
LL dfs(int x,int y)
{
if (y>m) return dfs(x+1,1);
if (x>n) return 1;
int cur=s[x-1][y]|s[x][y-1];
if(n+m-x-y>=k-one_num(cur)) return 0;
LL ans=0,tmp=-1;
for (int t=((~cur)&((1<<k)-1));t>0;t-=t&(-t))
{
int i=u[t&(-t)];
if ( !(cur&(1<<(i))) && ( a[x][y]==i+1 || !a[x][y] ) )
{
s[x][y]=cur|(1<<(i));
if (v[i+1]++) ans+=dfs(x,y+1);
else
{
if (tmp==-1) tmp=dfs(x,y+1);
ans+=tmp;
}
v[i+1]--;
ans%=MOD;
}
}
return ans;
}
int main()
{
while (~scanf("%d%d%d",&n,&m,&k))
{
memset(v,0,sizeof(v));
for (int i=0;i<=k;i++)
u[1<<i]=i;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);
v[a[i][j]]++;
}
if ((n+m-1)>k)
{
printf("0\n");
continue;
}
LL ans=dfs(1,1);
printf("%I64d\n",ans);
}
return 0;
}