POJ 3279 Fliptile

7 篇文章 0 订阅
5 篇文章 0 订阅

题目通道

解法

先枚举第一行的翻转的所有情况。
再根据第一行的枚举情况,综合,黑板的分布,确定下一行的翻转情况。前提是保证上一行的板块都是白。
接着枚举下一行,直到最后一行为止。
到最后一行时,已经确定了所有翻转情况,已经能确定前n-1行全部是白的,如果这时n行全部是白的,说明这个解是成立的。

AC代码

//#include"pch.h"
//#pragma warning(disable:4996);
#include<iostream>
#include<queue>
#include<cstring>
#include<string>
#include<sstream>
#include<map>
#include<vector>
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<stack>
#include<ctime>
using namespace std;
//#define _CRT_SECURE_NO_DEPRECATE;
//#define _CRT_SECURE_NO_WARNINGS;
#define rep(i,aa,bb) for(register int i=aa;i<=bb;i++)
#define rrep(i,aa,bb) for(register int i=aa;i>=bb;i--)
#define LL long long 
#define eps 0.000001
#define inf 0x3f3f3f3f
#define exp 0.000001
#define pai 3.141592654
#define random(x)   rand()%(x)
#define lowbit(x)   x&(-x)
inline int read()
{
	int x = 0, y = 1; char a = getchar(); while (a > '9' || a < '0') { if (a == '-')y = -1; a = getchar(); }
	while (a >= '0' && a <= '9') { x = 10 * x + a - '0'; a = getchar(); }return x * y;
}
#define N 17
int f[N][N]; int g[N][N], ans[N][N];
inline bool judge(int n, int m) {
	for (int i = 1; i <= m; i++) {
		int t = f[n][i] + f[n][i - 1] + f[n][i + 1] + f[n - 1][i] + g[n][i];
		if (t & 1)
			return 0; 
	}
	return 1; 
}
int mmin = inf; 
void dfs(int n, int m, int k, int num) {
	if (num > mmin)
		return; 
	if (k == n + 1) {
		if (judge(n, m) && mmin > num) {
			memcpy(ans, f, sizeof(f));
			mmin = num; 
		}
		return; 
	}
	int t = 0; 
	for (int i = 1; i <= m; i++) {
		if ((g[k - 1][i] + f[k - 1][i] + f[k - 1][i - 1] + f[k - 1][i + 1] + f[k - 2][i]) & 1) {
			f[k][i] = 1;
			t++;
		}
		else
			f[k][i] = 0; 
	}
	dfs(n, m, k + 1, num + t);
}
void todfs(int n, int m, int k, int num) {
	if (k == m+1 ) {
		dfs(n, m, 2, num);
/*		rep(i, 1, m)
			printf("%d ", f[1][i]);
		cout << endl; 
*/		return; 
	}
	f[1][k] = 0; 
	todfs(n, m, k + 1, num);
	f[1][k] = 1; 
	todfs(n, m, k + 1, num + 1);
}
int main()
{
	//	freopen("1.txt", "r", stdin);
	srand((int)time(0));
	std::ios::sync_with_stdio(false);
	int n, m;
	n = read(); m = read();
	rep(ai, 1, n)	rep(bi, 1, m) {
		g[ai][bi] = read();
	}
	todfs(n, m, 1, 0);
	if (mmin == inf )
		cout << "IMPOSSIBLE" << endl;
	else
		for (int i = 1; i <= n; i++)
		{
			for (int j = 1; j <= m; j++)
				cout << ans[i][j] << " ";
			cout << endl;
		}
	return 0;
}
这种写法不会使字典序最小
void todfs(int n, int m, int k, int num) {
	if (k == m + 1 ) {
		dfs(n, m, 2, num);
		return;
	}
	f[1][k] = 1; 
	todfs(n, m, k + 1, num + 1);
	f[1][k] = 0; 
	todfs(n, m, k + 1, num + 0);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值