CF293B. Distinct Paths

B. Distinct Paths
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

You have a rectangular n × m-cell board. Some cells are already painted some of k colors. You need to paint each uncolored cell one of the k colors so that any path from the upper left square to the lower right one doesn't contain any two cells of the same color. The path can go only along side-adjacent cells and can only go down or right.c++

Print the number of possible paintings modulo 1000000007 (109 + 7).ide

Input

The first line contains three integers n, m, k (1 ≤ n, m ≤ 1000, 1 ≤ k ≤ 10). The next n lines contain mintegers each — the board. The first of them contains m uppermost cells of the board from the left to the right and the second one containsm cells from the second uppermost row and so on. If a number in a line equals 0, then the corresponding cell isn't painted. Otherwise, this number represents the initial color of the board cell — an integer from 1 to k.this

Consider all colors numbered from 1 to k in some manner.spa

Output

Print the number of possible paintings modulo 1000000007 (109 + 7).three

Sample test(s)
input
2 2 4
0 0
0 0
output
48
input
2 2 4
1 2
2 1
output
0
input
5 6 10
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
output
3628800
input
2 6 10
1 2 3 4 5 6
0 0 0 0 0 0
output
4096

 

 

暴搜便可,有一個強力剪枝,對於當前全部未出現的顏色,接下來的狀態是一致的,因而只用算一次就好了。ip

 

#include <bits/stdc++.h>
using namespace std;
namespace my_useful_tools {
#define rep(_i, _k, _j) for(int _i = _k; _i <= _j;++_i)
#define foreach(_i, _s) for(typeof(_s.begin()) _i = _s.begin(); _i != _s.end();++_i)
#define pb push_back
#define mp make_pair
#define ipir pair<int, int>
#define ivec vector<int>
#define clr(t) memset(t, 0,sizeof t)
#define pse(t, v) memset(t, v,sizeof t)
#define brl puts("")
#define file(x) freopen(#x".in","r", stdin), freopen(#x".out","w", stdout)
	const int INF = 0x3f3f3f3f;
	typedef long long LL;
	typedef double DB;
	inline void pc(char c) { putchar(c); }
	template<class T> inline T gcd(T a, T b) { return b == 0 ? a : gcd(b, a % b); }
	template<class T> inline void W(T p) { if(p < 0) pc('-'), p = -p; if(p / 10 != 0) W(p / 10); pc('0' + p % 10); } // warning!! slower than printf
	template<class T> inline void Wn(T p) { W(p), brl; } template<class T> inline void W(T a, T b) { W(a), pc(' '), W(b); }
	template<class T> inline void Wn(T a, T b) { W(a), pc(' '), Wn(b); }
	template<class T> inline void W(T a, T b, T c) { W(a), pc(' '), W(b), pc(' '), W(c); } 
	inline char gchar() { char ret = getchar(); for(; ret == '\n' || ret == '\r' || ret == ' '; ret = getchar()); return ret; }
	template<class T> inline void fr(T&ret) { char c = ' '; int flag = 1; for(c = getchar(); c != '-' && !('0' <= c && c <= '9'); c = getchar()); 
		if(c == '-') flag = -1, ret = 0; else ret = c - '0'; for(c = getchar(); '0' <= c && c <= '9'; c = getchar()) ret = ret * 10 + c - '0';
		ret = ret * flag;
	}
	inline int fr() { int x; fr(x); return x; }
	template<class T> inline void fr(T&a, T&b) { fr(a), fr(b); } template<class T> inline void fr(T&a, T&b, T&c) { fr(a), fr(b), fr(c); }
	template<class T> inline T fast_pow(T base, T index, T mod = 2147483647, T ret = 1) {
		for(; index; index >>= 1, base = base * base % mod) if(index & 1) ret = ret * base % mod;
		return ret;
	}
	const int maxv = 100, maxe = 100;
	struct Edge {
		int edge, head[maxv], to[maxe], next[maxe];
		Edge() { edge = 0; memset(head, -1, sizeof head); }
		void addedge(int u, int v) {
			to[edge] = v, next[edge] = head[u];
			head[u] = edge++;
		}
	};
};
using namespace my_useful_tools;
 
class DistinctPaths {
	static const int mod = 1e9 + 7;
	static const int maxn = 10 + 1;
	static const int maxs = 1 << 15;
	int n, m, k;
	int a[maxn][maxn], ans, log2[maxs], f[maxn][maxn];
	int cnt[maxn];
	int dfs(int x, int y) {
		if(y == m + 1) {
			y = 1;
			++x;
		}
		if(x == n + 1) {
			return 1;
		}
		int s = f[x - 1][y] | f[x][y - 1];
		int ret = 0;
		int calced = -1;
		for(int t = (~s) & ((1 << k) - 1); t; t -= t & (-t)) {
			int p = log2[t & -t] + 1;
			if(a[x][y] == 0 || a[x][y] == p) {
				++cnt[p];
				f[x][y] = s | (t & -t);
				if(cnt[p] == 1) {
					if(calced == -1) calced = dfs(x, y + 1);
					ret += calced;
				} else if(cnt[p]) {
					ret += dfs(x, y + 1);
				}
				--cnt[p];
				if(ret >= mod) ret -= mod;
			}
		}
		return ret;
	}
	int solve() {
		fr(n, m, k);
		if(k < n + m - 1)
			return 0;
		rep(i, 1, n) rep(j, 1, m)
			fr(a[i][j]), ++cnt[a[i][j]];
		rep(i, 1, k) log2[1 << i] = i;
		return dfs(1, 1);
	}

public:
	void run() {
		Wn(solve());
	}
} solver;


int main() {
	solver.run();
 
	return 0;
}
相關文章
相關標籤/搜索