• 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,写法复杂,考虑的逻辑情况较多。
  • 相关阅读:
    LeetCode 121. Best Time to Buy and Sell Stock
    LeetCode 221. Maximal Square
    LeetCode 152. Maximum Product Subarray
    LeetCode 53. Maximum Subarray
    LeetCode 91. Decode Ways
    LeetCode 64. Minimum Path Sum
    LeetCode 264. Ugly Number II
    LeetCode 263. Ugly Number
    LeetCode 50. Pow(x, n)
    LeetCode 279. Perfect Squares
  • 原文地址:https://www.cnblogs.com/friedCoder/p/12245105.html
Copyright © 2020-2023  润新知