1. 程式人生 > >[NOIP2018 TG D2T2]填數遊戲

[NOIP2018 TG D2T2]填數遊戲

題目大意:$NOIP2018\;TG\;D2T2$

題解:skip2004部落格基礎上修改的,也是暴搜。

說明一下把vector改成陣列並不可以通過此題,記錄

結論:在$m>n+1$時答案為$3(n,m)$($(n,m)$表示長$m$高$n$的矩形的答案)

發現其中判斷右下角矩陣斜線全相等的部分可以優化,因為對於一條斜線,每次都搜右下角的矩陣,有很多部分都是重複搜的,完全可以每次搜只與它下面的一層比較,發現一條斜線中最多隻有一個$01$交界處,於是對於這一行進行特判,少搜一個,但是注意最下面的一行可能不是底,需要把整個矩陣搜一遍。

這樣似乎複雜度是不變的(我數學差),然後交了一下,發現還是會$TLE$,到洛谷$IDE$上測了一下是$1126ms$,於是加上一堆$register$和$const$就過了,最慢的點$925ms$。

我在洛谷$IDE$上又試了一下,原來全部搜一遍的程式碼加上$register$和$const$用時是$1263ms$(所有測試資料均為 8 9 )

卡點:$TLE$

 

C++ Code:

#include <cstdio>
#include <algorithm>
#define maxn 10
const int mod = 1e9 + 7;
inline int pw(int base, int p) {
	if (p < 0) return 1;
	int res = 1;
	for (; p; p >>= 1, base = static_cast<long long> (base) * base % mod) if (p & 1) res = static_cast<long long> (res) * base % mod;
	return res;
}
inline int min(int a, int b) {return a < b ? a : b;}
inline int max(int a, int b) {return a > b ? a : b;}

int n, m, ans;
int s[maxn][maxn];
struct node {
	int x, y;
	inline node() {};
	inline node(int __x, int __y) {x = __x, y = __y;}
} v[maxn << 1][maxn];
int tot[maxn << 1];

void dfs(const int X) {
	if (X < 2) {
		ans++;
		return ;
	}
	for (register node *i = v[X + 1]; i -> x; i++) {
		const int x = i -> x, y = i -> y;
		if (1 < x && x < n && y < m) {
			if (x == X) {
				if (s[x][y] == s[x - 1][y + 1]) {
					for (register int j = x; j < n; j++) {
						for (register int k = y + 2; k <= m; k++) if (s[j][k] != s[j + 1][k - 1]) return ;
					}
				} else if (x != 2) {
					for (register int j = x; j < n; j++) {
						for (register int k = y + 3; k <= m; k++) if (s[j][k] != s[j + 1][k - 1]) return ;
					}
				}
			} else {
				if (s[x][y] == s[x - 1][y + 1]) {
					for (register int j = y + 2; j <= m; j++) if (s[x][j] != s[x + 1][j - 1]) return ;
				} else if (x != 2) {
					for (register int j = y + 3; j <= m; j++) if (s[x][j] != s[x + 1][j - 1]) return ;
				}
			}
		}
	}
	for (register node *i = v[X]; i -> x; i++) s[i -> x][i -> y] = 1;
	dfs(X - 1);
	for (register node *i = v[X]; i -> x; i++) {
		s[i -> x][i -> y] = 0;
		dfs(X - 1);
	}
}
int main() {
	scanf("%d%d", &n, &m);
	if (n > m) std::swap(n, m);
	if (n == 1) {
		printf("%d\n", pw(2, m));
		return 0;
	}
	int res = pw(3, m - n - 1);
	m = min(n + 1, m);

	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) v[i + j][tot[i + j]++] = node(i, j);
	}
	dfs(n + m);
	printf("%lld\n", static_cast<long long> (ans) * res % mod);
	return 0;
}