zoukankan      html  css  js  c++  java
  • 紫书 例题7-14 UVa 1602(搜索+STL+打表)

    这道题想了很久不知道怎么设置状态,怎么拓展,怎么判重, 最后看了这哥们的博客 终于明白了。

    https://blog.csdn.net/u014800748/article/details/47400557


    这道题的难点在于怎么设置联通的状态,以及怎么拓展判重 .


    (1)状态:这里状态先定义了一个格子cell, 有x和y坐标。然后set<cell>表示一个联通块, 再用set<set<cell>>表示n个连块可以组成的所有联通块, 这里是集合套集合。 


    (2)拓展:每个格子向四个方向拓展。平移方面用到了标准化,感性的认识就是把这个图形整个移到了左下角(具体看代码), 然后旋转,这里有一个规律,就是所有的格子都是 (x, y) -> (y, -x) ,每次执行都会旋转90度,记得最后返回的是标准化后的图形。翻转的话,沿x轴翻转, 即(x, y)-> (x, -y), 然后再旋转四次,其中旋转180度后即是y轴翻转的结果,已经包含在里面了,所以不用另外写。 


        (3)最后就是打表,在多组数据而每组数据程序运行的时候会做重复的事情的时候,用打表会比直接做更快一些 


    代码如下

    #include<cstdio>
    #include<algorithm>
    #include<set>
    #define REP(i, a, b) for(int i = (a); i < (b); i++)
    using namespace std;
    
    struct cell
    {
    	int x, y;
    	cell(int x = 0, int y = 0) : x(x), y(y) {}
    	bool operator < (const cell& rhs) const
    	{
    		return x < rhs.x || (x == rhs.x && y < rhs.y); //固定写法 
    	}
    };
    
    const int MAXN = 11;
    typedef set<cell> piece;
    int ans[MAXN][MAXN][MAXN];
    set<piece> poly[MAXN];
    int dir[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
    
    inline piece normalize(piece p0)
    {
    	int minx = 15, miny = 15; //最大也就10,这里表示最大值 
    	for(auto& t : p0)
    	{
    		minx = min(minx, t.x);
    		miny = min(miny, t.y);
    	}
    	piece ret;
    	for(auto& t : p0) ret.insert(cell(t.x - minx, t.y - miny)); //这种遍历方式要c++11, 编译选项要加入-std=c++11 
    	return ret;
    }
    
    inline piece rotate(piece p0)
    {
    	piece ret;
    	for(auto& t : p0) ret.insert(cell(t.y, -t.x));
    	return normalize(ret);
    }
    
    inline piece file(piece p0)
    {
    	piece ret;
    	for(auto& t : p0) ret.insert(cell(t.x, -t.y));
    	return normalize(ret);
    }
    
    void add(piece p0, cell c)
    {
    	piece p = p0;
    	p.insert(c);
    	p = normalize(p);
    	
    	int id = p.size();
    	REP(i, 0, 4)
    	{
    		if(poly[id].count(p)) return;
    		p = rotate(p);
    	}
    	p = file(p);
    	REP(i, 0, 4)
    	{
    		if(poly[id].count(p)) return;
    		p = rotate(p);
    	}
    	
    	poly[id].insert(p);
    }
    
    void work()
    {
    	piece start;
    	start.insert(cell(0, 0));
    	poly[1].insert(start);
    	
    	REP(n, 2, MAXN)
    		for(auto& p : poly[n-1]) // 这里n-1,因为是从前一个拓展过来的 
    			for(auto& t : p)
    				REP(i, 0, 4)
    				{
    					cell temp(t.x + dir[i][0], t.y + dir[i][1]);
    					if(!p.count(temp)) add(p, temp);
    				}
    	
    	REP(n, 1, MAXN)
    		REP(w, 1, MAXN)
    			REP(h, 1, MAXN)
    			{
    				int cnt = 0;
    				for(auto& p : poly[n])
    				{
    					int maxx = 0, maxy = 0;
    					for(auto & t : p)
    					{
    						maxx = max(maxx, t.x);
    						maxy = max(maxy, t.y);
    					}
    					if(max(maxx, maxy) < max(w, h) && min(maxx, maxy) < min(w, h)) cnt++; //是否符合题目要求 
    				}
    				ans[n][w][h] = cnt;
    			}
    }
    
    int main()
    {
    	work();
    	int n, w, h;
    	while(~scanf("%d%d%d", &n, &w, &h))
    		printf("%d
    ", ans[n][w][h]);  //提前打表 
    	return 0;
    }

  • 相关阅读:
    Asp.Net2.0中的缓存
    webpartzone无法显示最小化和关闭按钮?
    TransactionScope分布式事务和非分布式事务
    JS获取GET参数的两种方法
    js 文件上传下载功能
    android动态设置布局LayoutInflater的使用详解
    Eclipse大括号换行显示
    Java强引用、 软引用、 弱引用、虚引用(转载)
    Android扭曲图像(水面落叶壁纸初步实现)
    win7系统自带的屏幕录制软件
  • 原文地址:https://www.cnblogs.com/sugewud/p/9819607.html
Copyright © 2011-2022 走看看