ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【题解】[BalticOI 2010 Day2] Mines

2022-07-21 12:00:06  阅读:125  来源: 互联网

标签:return int 题解 rep Day2 Mines 枚举 && false


给定一个 \(N\times M\) 的矩阵 \(A\),你需要构造一个 \(0/1\) 矩阵 \(B\),满足 \(A_{i,j}\) 恰好等于它自己和相邻 \(8\) 个位置的 \(B\) 的和。

很适合比赛的一道提交答案题。

我们发现非常类似扫雷游戏,那么我们考虑从一个方向递推过去。

首先枚举左上角四个格子中的数,最多有 \(16\) 种情况,然后枚举第一行和第一列的数,那么剩下的位置可以被我们 \(N\times M\) 递推出来。

直接枚举是 \(2^{N+M}\) 的,\(N,M\) 非常大,这辈子都跑不完,同时这是提交答案题,我们可以考虑各种复杂度是不那么优秀的算法。

我们先写成搜索的构架,然后考虑慢慢优化。包括优化搜索顺序,我们按搜一行然后搜一列的方式交替搜索行和列。对于当前位置不合法及时返回。以及在枚举左上角后,预处理每一行和每一列的起始。

直接跑还是很慢,我们发现将地图旋转或翻转后答案本质不变,所以我们可以将地图转化为 \(8\) 个本质相同的地图,开多个程序同时跑即可。同时观察数据点,可以预处理下哪些行的 \(1\) 多,哪些列的 \(1\) 多。时间最长的点 \(6\) 号点也就跑了 \(5\) 分钟。个人认为 \(6\) 号点时间长是因为 \(N,M\) 的差比较大,并且 \(N,M\) 都 \(\ge 100\)。

以下是参考代码,但只用这一份代码是无法跑出所有测试点的。

#define N 605
int n, m, a[N][N], u[N][N], f[N][N]; char ch[N];
int r[N], c[N];
inline bool check(int x,int y,int op){
	if(y > m || (x <= n && x <= y)){
		u[x][1] = op, u[x][2] = r[x] - op;
		if(u[x][2] < 0 || u[x][2] > 1)return false;
		rep(i, 3, y - 1){
			u[x][i] = a[x - 1][i - 1] - f[x - 1][i - 1] - u[x][i - 2] - u[x][i - 1] - u[x - 1][i] - u[x - 2][i];
			if(u[x][i] < 0 || u[x][i] > 1)return false;
			f[x][i] = u[x][i] + u[x][i - 1] + u[x - 1][i] + u[x - 1][i - 1];
			if(x == n && f[x][i] + u[x][i - 2] + u[x - 1][i - 2] != a[x][i - 1])return false;
		}
		if(y > m && f[x][m] + u[x - 2][m] + u[x - 2][m - 1] != a[x - 1][m])return false;
	}
	else{
		u[1][y] = op, u[2][y] = c[y] - op;
		if(u[2][y] < 0 || u[2][y] > 1)return false;
		rep(i, 3, x - 1){
			u[i][y] = a[i - 1][y - 1] - f[i - 1][y - 1] - u[i - 2][y] - u[i - 1][y] - u[i][y - 1] - u[i][y - 2];
			if(u[i][y] < 0 || u[i][y] > 1)return false;
			f[i][y] = u[i][y] + u[i][y - 1] + u[i - 1][y] + u[i - 1][y - 1];
			if(y == m && f[i][y] + u[i - 2][y] + u[i - 2][y - 1] != a[i - 1][y])return false;
		}
		if(x > n && f[n][y] + u[n][y - 2] + u[n - 1][y - 2] != a[n][y - 1])return false;
	}
	return true;
}
void dfs(int x,int y){
	if(x > n && y > m){
		if(f[n][m] == a[n][m]){
			rp(i, n){rp(j, m)if(u[i][j])pc('X'); else pc('.'); el;}
			exit(0);
		}return ;
	}
	if(y > m || (x <= n && x <= y)){
		if(check(x, y, 0))dfs(x + 1, y);
		if(check(x, y, 1))dfs(x + 1, y);
	}
	else{
		if(check(x, y, 0))dfs(x, y + 1);
		if(check(x, y, 1))dfs(x, y + 1);
	}
}
int main() {
	read(n, m);
	rp(i, n){
		scanf("%s", ch + 1);
		rp(j, m)a[i][j] = ch[j] - '0';
	}
	rep(s, 0, 15)if(a[1][1] == __builtin_popcount(s)){
		u[1][1] = s & 1, u[1][2] = (s >> 1) & 1, 
		u[2][1] = (s >> 2) & 1, u[2][2] = (s >> 3) & 1;
		r[1] = u[1][1] + u[1][2], r[2] = u[2][1] + u[2][2];
		c[1] = u[1][1] + u[2][1], c[2] = u[1][2] + u[2][2];
		bool flag = true;
		rep(i, 3, n)r[i] = a[i - 1][1] - (a[i - 2][1] - r[i - 3]), flag &= r[i] >= 0 && r[i] <= 2;
		rep(i, 3, m)c[i] = a[1][i - 1] - (a[1][i - 2] - c[i - 3]), flag &= c[i] >= 0 && c[i] <= 2;
		if(!flag)continue;
		rep(i, 2, n)f[i][2] = r[i] + r[i - 1];
		rep(i, 2, m)f[2][i] = c[i] + c[i - 1];
		if(a[n][1] == f[n][2] && a[1][m] == f[2][m])dfs(3, 3);
	}
	return 0;
}
/*
4 4
2332
3442
3331
3320
1 1 1 0
0 0 0 1
0 1 0 0
1 1 0 0
*/

标签:return,int,题解,rep,Day2,Mines,枚举,&&,false
来源: https://www.cnblogs.com/7KByte/p/16501449.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有