• poj3279 Fliptile


    #include <iostream>
    #include <cstring>
    using namespace std;
    // 邻接格子的坐标
    const int dx[5] = {-1, 0, 0, 0, 1};
    const int dy[5] = {0, -1, 0, 1, 0};
    const int MAX_M = 16;
    const int MAX_N = 16;
    int M, N;
    int tile[MAX_M][MAX_N];
    
    int opt[MAX_M][MAX_N]; // 保存最优解
    int flip [MAX_M][MAX_N]; // 保存中间结果
    
    // 查询(x, y)的颜色
    int get(int x, int y)
    {
    	int c = tile[x][y];
    	for (int d = 0; d < 5; d++)
    	{
    		int x2 = x + dx[d], y2 = y + dy[d];
    		if (x2 >= 0 && x2 < M && y2 >= 0 && y2 < N)
    		{
    			c += flip[x2][y2];
    		}
    	} 
    	return c % 2;
    }
    
    // 求出第1行确定情况下的最小操作次数
    int calc()
    {
    	// 求出从第2行开始的翻转方法
    	for (int i = 1; i < M; i++)
    	for (int j = 0; j < N; j++)
    	{
    		if (get(i - 1, j) != 0)
    		{
    			// 如果同列的上一行为黑色,则必须翻转,因为此后,只有该点的翻转可以改变正上方的棋子颜色了
    			flip[i][j] = 1; 
    		}
    	}
    	
    	// 判断最后一行是否空白
    	for (int j = 0; j < N; j++)
    	if (get(M - 1, j)) // 无解 
    	return -1;
    	
    	//统计翻转的次数
    	int res = 0;
    	for (int i = 0; i < M; i++)
    	for (int j = 0; j < N; j++)
    	res += flip[i][j];
    	
    	return res; 
    } 
     
    void solve()
    {
    	int res = -1;
    	memset(opt, 0, sizeof(opt));
    	// 按照字典序开始尝试第一行所有的可能性
    	for (int i = 0; i < 1 << N; i++)
    	{
    		memset(flip, 0, sizeof(flip)); // 每次必须重新清空flip 
    		for (int j = 0; j < N; j++)
    		{
    			flip[0][N - 1 - j] = i >> j & 1;
    		}
    		
    		int num = calc();
    		
    		if (num >= 0 && (res == -1 || res > num))
    		{
    			res = num;
    			memcpy(opt, flip, sizeof(flip));
    		}
    	} 
    	
    	if (res == -1) cout << "IMPOSSIBLE" << endl;
    	else
    	{
    		for (int i = 0; i < M; i++)
    		{
    			for (int j = 0; j < N - 1; j++)
    			cout << opt[i][j] << " ";
    			
    			cout << opt[i][N - 1] << endl;
    		}
    	}
    }
    
    int main()
    {
    	while (cin >> M >> N)
    	{
    		for (int i = 0; i < M; i++)
    		for (int j = 0; j < N; j++)
    		cin >> tile[i][j];
    		
    		solve();
    	}
    
    	return 0;
    }

  • 相关阅读:
    实战篇之实现 OutLook 中以 EDM 形式发送通知邮件
    ASP.NET MVC5 之路由器
    ASP.NET MVC5 之数据迁移
    说不出的烦
    ASP.NET MVC5 之 Log4Net 的学习和使用
    读取配置文件参数和文件路径
    序列化和反序列化示例
    面向对象之封装
    面向对象4之常用的乱七八糟
    面向对象三之继承和派生
  • 原文地址:https://www.cnblogs.com/mofushaohua/p/7789499.html
Copyright © 2020-2023  润新知