[CF293B]Distinct Paths_搜索_剪枝

Distinct Paths

题目链接http://codeforces.com/problemset/problem/293/B

数据范围:略。


题解

带搜索的剪枝....

想不到吧.....

但是剪枝也比较简单,就是能想到的剪枝都加上能过的那种搜索题。

代码

#include <bits/stdc++.h>

#define setIO(s) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout) 

using namespace std;

const int mod = 1000000007 ;

int Log[1100], n, m, k, a[21][21], f[21][21], v[21];

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, re = 0;
	int S = ~s & ((1 << k) - 1);
	if (n + m - x - y + 1 > Log[S]) {
		return 0;
	}
	for (int t = 0; t < k; t ++ ) {
		if (S & (1 << t)) {
			if (a[x][y] == 0 || a[x][y] == t + 1) {
				v[t + 1] ++ ;
				f[x][y] = s | (1 << t);
				if (v[t + 1] == 1) {
					if (calc == -1) {
						calc = dfs(x, y + 1);
					}
					re += calc;
				}
				else {
					re += dfs(x, y + 1);
				}
				if (re >= mod) {
					re -= mod;
				}
				v[t + 1] -- ;
			}
		}
	}
	return re;
}

int main() {
	// setIO("search&force");
	for (int i = 1; i < 1024; i ++ ) {
		Log[i] = Log[i >> 1] + (i & 1);
	}
	// int T;
	// cin >> T ;
	// while (T -- ) {
		// memset(v, 0, sizeof v);
		// memset(f, 0, sizeof f);
	cin >> n >> m >> k ;
	if (n + m - 1 > k) {
		puts("0");
		return 0;
	}
	for (int i = 1; i <= n; i ++ ) {
		for (int j = 1; j <= m; j ++ ) {
			scanf("%d", &a[i][j]);
			v[a[i][j]] ++ ;
		}
	}
	cout << dfs(1, 1) << endl ;
	return 0;
}
posted @ 2019-10-29 20:12  JZYshuraK_彧  阅读(148)  评论(0编辑  收藏  举报