zoukankan      html  css  js  c++  java
  • UVA

    /*
    题目链接:
    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=63
    
    这题也是比较考思维,好像没什么特别的技巧和知识点,但是自己想的时候,怎么也想不到用 vector< vector<card> > 处理的这种方式...
    
    可能STL学的还不够熟练吧...
    
    参考了别人的题解和思路,别人的思路真是太巧妙了,引用一句评价:
    “每次只输入一张牌,马上向前查看是否能匹配,而不是一副牌都分配好后再来插入和删除,效率高,实现效果好。”
    
    总结一下:值得重做的题,可以极大加深对STL的理解。
    
    而且,如果一开始不看题解,而是先自己想该怎么实现,很久没有想明白以后,再去看题解,更能发现,这个博主的思路真的非常非常巧妙,让人想要拊掌称叹
    */


    /*
    参考借鉴思路于:
    http://blog.csdn.net/bb2b2bbb/article/details/26484267
    */
    #include <iostream>
    #include <vector>
    #define rep(i, j, n) for (int i = j; i < n; i++)
    using namespace std;
    struct card
    {
    	char number, color;
    	card(char n = ' ', char c = ' '):number(n), color(c)
    	{
    	}
    };
    vector<vector<card> > vec;
    
    int deal(card c, int size)
    { //该函数返回牌插入的位置,因为牌的规则包含各种 match 和 移动 的情况的处理 
    	int tp; //temp
    	while (size > 0) //开始判断能否 match 、能否移动,可左移一格也可左移格时,移动3格,所以先判断3格的情况 
    	{
    		if (size >= 3)
    		{
    			tp = (int)vec[size - 3].size() - 1; //最顶端的牌才能参与 match 或者参与移动,tp是最顶端的牌的下标
    			card& c0 = vec[size - 3][tp];
    			if ( c0.number == c.number || c0.color == c.color )
    			{
    				size -= 3;
    				continue;
    			} 
    		}
    		if (size >= 1)
    		{
    			tp = (int)vec[size - 1].size() - 1; //最顶端的牌才能参与 match 或者参与移动,tp是最顶端的牌的下标
    			card& c0 = vec[size - 1][tp];
    			if ( c0.number == c.number || c0.color == c.color )
    			{
    				size -= 1;
    				continue;
    			} 
    		}
    		break; //如果有移动,则可不断继续判断,是否仍满足移动的条件,直到不能移动为止,不能移动时,跳出循环 
    	}
    	return size; //返回该牌最终放置的位置 
    }
    
    void solve()
    {
    	char input[3];
    	while (cin >> input && input[0] != '#')
    	{
    		int num = 52;
    		while (num--)
    		{
    			card c(input[0], input[1]);
    			int pos = deal(c, (int)vec.size());
    			if (pos == (int)vec.size()) //卡片没有移动,直接插入
    			{
    				vector<card> v(1, c);
    				vec.push_back(v);
    			}
    			else //卡片能移动,pos是卡片最终放置的位置 
    			{
    				vec[pos].push_back(c);
    		Again: 	rep( i, pos + 1, (int)vec.size() )
    				//每次一旦有卡片插入,则跳到卡片插入位置之后,找其后还有没有可插入的卡片;所以相当于是进入了一个全新的循环,和原来的循环完全不同了。这点用标号来实现最为简洁,所以尽管不建议用goto,但在这里,我想不到比goto更好的代替方式了 
    				{
    					card d = vec[i][(int)vec[i].size() - 1];
    					int loc = deal(d, i); //loc::location,这里的处理挺有意思,把已经遍历过的牌堆的后一个牌堆,这个牌堆上的最顶部的牌,当作是要插入已经排好的那些牌堆中,看看这张牌能不能移动 
    					if ( loc != i )
    					{
    						vec[loc].push_back(d); //把这种牌插入该移动到的位置 
    						vec[i].pop_back(); //把这张牌从原来的堆顶移除
    						if (vec[i].empty())
    						vec.erase(vec.begin() + i); //如果删完以后,牌堆空了,整个牌堆移除
    						pos = loc; //更新下已经拍好的牌堆的数目,使得从已经排好的牌堆的后面,再来找有没有可以移动的牌堆 
    						goto Again; 
    					}
    				}
    			}
    			if (!num) break; //这组的52张牌全部发完,开始处理下组数据
    			cin >> input; //52张没发完,接着发牌 
    		}
    		cout << (int)vec.size() << (vec.size() != 1 ? " piles remaining: ":" pile remaining: ");
    		rep(i, 0, (int)vec.size())
    		{
    			if ( i != vec.size() - 1 ) cout << vec[i].size() << " ";
    			else cout << vec[i].size() << endl;
    		}
    		vec.clear();
    	}
    }
    
    int main()
    {
    	solve();
    	return 0;
    }

    /*
    查阅的其他资料:
    http://mikixiyou.iteye.com/blog/1754413
    http://www.cnblogs.com/freeopen/p/5482962.html
    http://blog.csdn.net/glrh123/article/details/45542549
    */


  • 相关阅读:
    web前端的发展态势
    AngularJs 简单入门
    css代码优化篇
    git提交报错:Please make sure you have the correct access rights and the repository exists.
    Activiti工作流框架学习
    遍历map集合的4种方法
    js设置日期、月份增加减少
    Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
    webservice_rest接口_学习笔记
    相互匹配两个list集合+动态匹配${}参数
  • 原文地址:https://www.cnblogs.com/mofushaohua/p/7789346.html
Copyright © 2011-2022 走看看