zoukankan      html  css  js  c++  java
  • POJ 1753

    题目大意:

    有 4x4 的正方形,每个格子要么是黑色,要么是白色,当把一个格子的颜色改变(黑->白或者白->黑)时,其周围上下左右(如果存在的话)的格子的颜色也被反转,问至少反转几个格子可以使 4x4 的正方形变为纯白或者纯黑?

    //1753
    //动态规划
    //Flip Game
    
    #include<iostream>
    #include<string>
    #include<bitset>
    
    #define MAX 100000
    
    using namespace std;
    
    typedef unsigned short grid;
    
    //翻转格子
    //flipPos : 翻转格子的位置;  item: 被翻转的对象
    //返回翻转后的grid
    grid Flip( int flipPos, grid item )
    {
    	item ^= (1 << (flipPos-1) );
    	if(flipPos > 4){
    		item ^= (1 << (flipPos-4-1) );
    	}
    	if(flipPos % 4 != 1){
    		item ^= (1 << (flipPos-1-1) );
    	}
    	if(flipPos % 4 != 0){
    		item ^= (1 << (flipPos+1-1) );
    	}
    	if(flipPos < 13){
    		item ^= (1 << (flipPos+4-1) );
    	}
    
    	return item;
    }
    
    
    
    int main(int argc, char *argv[])
    {
    	string str;
    	string lineStr;
    	grid gridOne = 0;
    	int i;
    
    	//input
    	i = 0;
    	while( i++ < 4 ){
    		cin >> lineStr;
    		str += lineStr;
    	}
    
    	//change string to unsigned shor
    	//b->1, w->0
    	i = 15;
    	for( string::iterator c = str.begin();  c != str.end();  c++ ){
    		if( *c == 'b' ){
    			gridOne |= (1 << i);
    		}
    		i--;
    	}
    
    	if( gridOne == 0 ||  gridOne == 0xffff ){
    		cout << 0 << endl;
    		return 0;
    	}
    	
    
    	//calculate time
    	typedef struct Table{
    		grid gridItem;
    		int step;	//第几次翻转
    		int pos;
    	}Table;
    
    	Table table[MAX];
    	bool flags[MAX] = {false};	//对已经出现过的情况做标记;没有这个可能会出现死循环
    
    	table[0].gridItem = gridOne;
    	table[0].pos = -1;
    	table[0].step = 0;
    	flags[gridOne] = true;	
    
    	grid item;
    	int current = 0;	//当前k情况
    	int capacity = 1;	//所有可能情况的总数
    
    	//test
    	//cout << str << endl;
    	//cout << bitset<sizeof(grid)*8>(gridOne) << endl;
    	//cout << "test end";
    	
    
    	while( current != capacity ){
    		item = table[current].gridItem;
    
    		//位置从1开始
    		for(i=1; i<17; i++){
    			if( table[current].pos != i ){
    				grid newItem = Flip(i, item);
    
    				if( flags[newItem] == false ){
    					table[capacity].gridItem = newItem;
    					table[capacity].pos = i;
    					table[capacity].step = table[current].step + 1;
    					flags[newItem] = true;
    
    					if( table[capacity].gridItem == 0 || table[capacity].gridItem == 0xffff ){
    						cout << table[capacity].step << endl;
    						return 0;
    					}
    
    					capacity++;
    				}
    			}
    		}
    		current++;
    	}	
    
    	cout << "Impossible" << endl;
    	return 0;
    }
    

    下面说说自己的收获

    • 创建结构数组比结构体里包含数组要方便
    • 这里使用线性存储树结构
    • 在使用动态规划时,不仅仅要注意“存储表”的创建,同时更重要的是去除重复情况,这题使用flags标记来过滤重复的grid。这题不过滤重复情况可能会陷入死循环。
    • 这题通过结构体来记录翻转次数step,这种方法虽然空间消耗大,但是写法简单。如果只用一个变量记录翻转次数step,写法复杂,考虑的逻辑情况较多。
  • 相关阅读:
    VC++中使用内存映射文件处理大文件
    802.1x协议解析
    Jscript中window.setInterval和window.setTimeout区别
    在C#中使用代理的方式触发事件
    JavaScript实用的一些技巧
    控制C#编的程序内存的占用
    纯C#钩子实现及应用(转)
    DES的建立过程
    C# 显示占用内存
    解决“由于应用程序的配置不正确,应用程序未能启动,重新安装应用程序可能会纠正这个问题”
  • 原文地址:https://www.cnblogs.com/friedCoder/p/12245105.html
Copyright © 2011-2022 走看看