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
    */


  • 相关阅读:
    40种网页常用小技巧(javascript)
    伸缩效果
    震动的超链
    一个模仿图片透明渐变做的表格颜色渐变效果
    荧 光 效 果
    用LoadRunner编写socket应用的测试脚本
    突发奇想写的一篇小科幻(如果可以叫做科幻的话)
    《软件性能测试过程详解与案例剖析》一书在Chinapub上8月份的销售排名持续上升
    建立高效的测试团队
    探索性测试(Exploratory Testing)概述
  • 原文地址:https://www.cnblogs.com/mofushaohua/p/7789346.html
Copyright © 2011-2022 走看看