• POJ 3279 Fliptile.cpp


    Description:

    有一个n*m的格子,每个格子都有黑白两面(0表示白色,1表示黑色)。我们需要把所有的格子都反转成黑色,每反转一个格子,它上下左右的格子都会跟着反转。请求出用最小步数完成反转时每个格子反转的次数。有多个解时,输出字典序最小的一组。

    Analysis:

    一个格子没有必要翻转两次。
    如果第一行翻转方法确定了,那么递推下面所有行就都确定了。
    先确定第一行翻转方法O(2^n),接下来每一行,如果某一个格子的上一行格子是黑色的,那么就翻转这个格子。
    时间复杂度O(nm2^n)

    Code

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define White 0
    #define Black 1
    using namespace std;
    const int N = 20;
    const int dx[5] = {-1,0,0,0,1};
    const int dy[5] = {0,-1,0,1,0};
    int tile[N][N],flip[N][N],opt[N][N];
    int m,n;
    int getColour(int x,int y)
    {
    	int c = tile[x][y];
    	for(int d = 0;d < 5;++d)
    	{
    		int x1 = x + dx[d],y1 = y + dy[d];
    		if((0 <= x1 && x1 < m) && (0 <= y1 && y1 < n))
    		{
    			c += flip[x1][y1];
    		}
    	}
    	return c % 2;
    }
    int calc()
    {
    	for(int i = 1;i < m;++i)
    	{
    		for(int j = 0;j < n;++j)
    		{
    			if(getColour(i-1,j) == Black)
    			{
    				flip[i][j] = 1;
    			}
    		}
    	}
    	for(int i = 0;i < n;++i)
    	{
    		if(getColour(m - 1,i) == Black)
    		{
    			return -1;
    		}
    	}
    	int ans = 0;
    	for(int i = 0;i < m;++i)
    	{
    		for(int j = 0;j < n;++j)
    		{
    			ans += flip[i][j];
    		}
    	}
    	return ans;
    }
    void solve()
    {
    	int ans = 10000;
    	int flag = 1;
    	for(int i = 0;i < (1 << n);++i)
    	{
    		memset(flip,0,sizeof(flip));
    		for(int j = 0;j < n;++j)
    		{
    			flip[0][n - j - 1] = (i >> j) & 1;
    		}
    		int num = calc();
    		if(num < ans && num > 0)
    		{
    			ans = num;
    			flag = 0;
    			memcpy(opt,flip,sizeof(flip));
    		}
    	}
    	if(flag)
    	{
    		printf("IMPOSSIBLE
    ");
    	}
    	else{
    		for(int i = 0;i < m;++i)
    		{
    			for(int j = 0;j < n;++j)
    			{
    				printf("%d%c",opt[i][j],j + 1 == n ? '
    ' : ' ');
    			}
    		}
    	}
    }
    int main()
    {
    	scanf("%d%d",&m,&n);
    	for(int i = 0;i < m;++i)
    	{
    		for(int j = 0;j < n;++j)
    		{
    			scanf("%d",&tile[i][j]);
    		}
    	}
    	solve();
    	return 0;
    }
    
    岂能尽如人意,但求无愧我心
  • 相关阅读:
    Java中的4种代码块
    Java enum(枚举)的用法详解(转)
    Java 可变参数列表
    SQL Server 查询处理中的各个阶段(SQL执行顺序)
    SQL Server 数据查询 整理
    MYSQL常用命令
    SQL的主键和外键约束(转)
    Servlet工作原理(转)
    servlet、genericservlet、httpservlet之间的区别(转)
    关于MyEcplise中常见的问题和解决方案
  • 原文地址:https://www.cnblogs.com/Zforw/p/11178202.html
Copyright © 2020-2023  润新知