zoukankan      html  css  js  c++  java
  • 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.

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

    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.

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

    Output

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

    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

    暴搜即可,有一个强力剪枝,对于当前所有未出现的颜色,接下来的状态是一致的,于是只用算一次就行了。

    #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 == '
    ' || ret == '
    ' || 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;
    }
    
  • 相关阅读:
    2.采用字符的移位方式实现字符文本加密解密。
    用自己的算法实现startsWith和endsWith功能。
    采用多种算法,模拟摇奖:从1-36中随机抽出8个不重复的数字
    输入5个数用冒泡排序进行从小到大排列
    题目六:控制台输入年龄,根据年龄输出不同的提示
    题目五:控制台输出三角形和菱形
    题目四:控制台输出九九乘法表
    百马百担
    classNum 表示学生的班号,例如“class05”。 有如下List  List list = new ArrayList();
    已知有十六支男子足球队参加2008 北京奥运会。写一个程序,把这16 支球队随机分为4 个组。采用List集合和随机数     2008 北京奥运会男足参赛国家:  科特迪瓦,阿根廷,澳大利亚,塞尔维亚,荷兰,尼日利亚、日本,美国,中国,新西 兰,巴西,比利时,韩国,喀麦隆,洪都拉斯,意大利
  • 原文地址:https://www.cnblogs.com/hzf-sbit/p/4041759.html
Copyright © 2011-2022 走看看