记忆化搜索 codevs 2241 排序二叉树

codevs 2241 排序二叉树

★   输入文件:bstree.in   输出文件:bstree.out   简单对比
时间限制:1 s   内存限制:128 MB

【问题描述】

一个边长为n的正三角形可以被划分成若干个小的边长为1的正三角形,称为单位三角形。

如右图,边长为3的正三角形被分成三层共9个小的正三角形,我们把它们从顶到底,从左到右以1~9编号,见右图。同理,边长为n的正三角形可以划分成n2个单位三角形。

 

 四个这样的边长为n的正三角形可以组成一个三棱锥。我们将正三棱锥的三个侧面依顺时针次序(从顶向底视角)编号为A, B, C,底面编号为D。侧面的A, B, C号三角形以三棱锥的顶点为顶,底面的D号三角形以它与A,B三角形的交点为顶。左图为三棱锥展开后的平面图,每个面上标有圆点的是该面的顶,该图中侧面A, B, C分别向纸内方向折叠即可还原成三棱锥。我们把这A,B、C、D四个面各自划分成n2个单位三角形。

 

   对于任意两个单位三角形,如有一条边相邻,则称它们为相邻的单位三角形。显然,每个单位三角形有三个相邻的单位三角形。现在,把1—4n2分别随机填入四个面总共4n2个单位三角形中。

    现在要求你编程求由单位三角形组成的最大排序二叉树。所谓最大排序二叉树,是指在所有由单位三角形组成的排序二叉树中节点最多的一棵树.对于任一单位三角形,可选它三个相邻的单位三角形中任意一个作为父节点,其余两个分别作为左孩子和右孩子。当然,做根节点的单位三角形不需要父节点,而左孩子和右孩于对于二叉树中的任意节点来说并不是都必须的。

【输入】

    输入文件为bstree.in。其中第一行是一个整数n(1<=n<=18),随后的4n2个数,依次为三棱锥四个面上所填的数字。

【输出】

输出文件为bstree.out。其中仅包含一个整数,表示最大的排序二又树所含的节点数目。

【样例输入】

3

19 33 32 31 29 3 5 4 30

22 24 20 21 12 24 23 34 35

14 13 15 26 18 17 8 16 27

11 10 9 1 28 7 2 6 36

【样例】

输入文件对应下图:

【样例输出】

17

【提示】

 

输出样例文件对应的最大排序二叉树如下图所示:

 

 

  1 /*正解代码:我给加了注解,建立排序二叉树的左右子树的时候,一定要注意建立的上下界,否则就不是排序二叉树*/
  2 /*
  3 【算法分析】
  4     在讨论问题的解法之前,我们先来看看二叉排序树的性质。
  5     二叉排序树是一棵满足下列性质的二又树:
  6     性质1  它或是一棵空树,或是一棵二叉树,满足左子树的所有结点的值都小于根结点的值,右子树的所有结点的值都大于根结点的值;
  7     性质2  它若有子树,则它的子树也是二叉排序树。
  8     根据性质1,我们可以知道,二叉排序树的左右子树是互不交叉的。也就是说,如果确定了根结点,那么我们就可以将余下的结点分成两个集合,其中一个集合的元素可能在左子树上,另一集合的元素可能在右子树上,而没有一个结点同时可以属于两个集合。这一条性质,满足了无后效性的要求,正因为二叉排序树的左右子树是互不交叉的,所以如果确定根结点后,求得的左子树,对求右子树是毫无影响的。因此,如果要使排序树尽可能大,就必须满足左右子树各自都是最大的,即局部最优满足全局最优。
  9     根据性质2,二叉排序树的左右子树也是二叉排序树。而前面已经分析得到,左右子树也必须是极大的。所以,求子树的过程也是一个求极大二叉排序树的过程,是原问题的一个子问题。那么,求二叉排序树的过程就可以分成若干个阶段来执行,每个阶段就是求一棵极大的二叉排序子树。
 10     由此,我们看到,本题中,二叉排序树满足阶段性(性质2)和无后效性(性质1),可以用动态规划解决。
 11     下面来看具体解决问题的方法。
 12     不用说,首先必须对给出的正三棱锥建图,建成一张普通的无向图。
 13     根据正三棱锥中结点的性质,每个结点均与三个结点相连。而根据二叉排序树的性质,当一个结点成为另一个结点的子结点后,它属于左子树还是右子树也就确定下来了。所以,可以对每个结点进行状态分离,分离出三种状态——该结点作为与它相连的三个结点的子结点时,所得的子树的状态。但是,一个子结点可以根据它的父结点知道的仅仅是该子树的一个界(左子树为上界,右子树为下界),还有一个界不确定,所以还需对分离出来的状态再进行状态分离,每个状态代表以一个值为界(上界或下界)时的子树状态。
 14     确定了状态后,我们要做的事就是推出状态转移方程。
 15     前面已经提到,一个极大的二叉排序树,它的左右子树也必须是极大的。因此,如果我们确定以结点n为根结点,设所有可以作为它左子结点的集合为N1,所有可以作为它右子结点的集合为N2,则以n为根结点、结点大小在区间[l, r]上的最大二叉排序树的结点个数为:
 16 【动态规划】排序二叉树
 17     我们所要求的最大的二叉排序树的结点个数为:【动态规划】排序二叉树
 18     从转移方程来看,我们定义的状态是三维的。那么,时间复杂度理应为O(n3)。其实并非如此。每个结点的状态虽然包含下界和上界,但是不论是左子结点还是右子结点,它的一个界取决于它的父结点,也就是一个界可用它所属的父结点来表示,真正需要分离的只有一维状态,要计算的也只有一维。因此,本题时间复杂度是O(n2)(更准确的说应该是O(3n2))。
 19     此外,由于本题呈现一个无向图结构,如果用递推形式来实现动态规划,不免带来很大的麻烦。因为无向图的阶段性是很不明显的,尽管我们从树结构中分出了阶段。不过,实现动态规划的方式不仅仅是递推,还可以使用搜索形式——记忆化搜索。用记忆化搜索来实现本题的动态规划可以大大降低编程复杂度。
 20 */
 21 /*----------------代码----------------*/
 22 #include<iostream>
 23 #include<cstdio>
 24 using namespace std;
 25 const int Limitn=18+2;
 26 const int Limitpoint=1296+4;
 27 int n;
 28 int s[5][20][40];
 29 int c[Limitpoint][4];
 30 bool vis[Limitpoint][Limitpoint];
 31 int f[Limitpoint][4][Limitpoint];
 32 int best;
 33 void init()
 34 {
 35     scanf("%d",&n);/*s[k][i][j],第k个三角形的第i行的第j个*/
 36     for (int k=1;k<=4;k++)
 37         for (int i=1;i<=n;i++)
 38             for (int j=1;j<=i*2-1;j++)
 39                 scanf("%d",&s[k][i][j]);
 40 }
 41 void link(int a,int b)
 42 {
 43     if (!vis[a][b])
 44     {
 45         vis[a][b]=1;
 46         c[a][++c[a][0]]=b;/*邻接表建边,a不是节点的编号,而是一个数*/
 47     }
 48     if (!vis[b][a])
 49     {
 50         vis[b][a]=1;
 51         c[b][++c[b][0]]=a;
 52     }
 53 }
 54 void make_graph()
 55 {
 56     for (int k=1;k<=4;k++)
 57         for (int i=2;i<n;i++)
 58             for (int j=2;j<i*2-1;j++)
 59             {/*三角形内部建边*/
 60                 link(s[k][i][j],s[k][i][j-1]);
 61                 link(s[k][i][j],s[k][i][j+1]);
 62                 if (j%2)
 63                     link(s[k][i][j],s[k][i+1][j+1]);
 64                 else
 65                     link(s[k][i][j],s[k][i-1][j-1]);
 66             }
 67     for (int k=1;k<=4;k++)
 68         for (int j=2;j<=n*2-1;j+=2)
 69         {/*三角形最后一层建边*/
 70             link(s[k][n][j],s[k][n][j-1]);
 71             link(s[k][n][j],s[k][n][j+1]);
 72             link(s[k][n][j],s[k][n-1][j-1]);
 73         }
 74     for (int k=1,i=1;k<=n;k++,i++)
 75     {/*相邻的棱三角形建边*/
 76         link(s[1][i][1],s[3][i][i*2-1]);
 77         link(s[1][i][i*2-1],s[2][i][1]);
 78         link(s[2][i][i*2-1],s[3][i][1]);
 79     }
 80     for (int j=1;j<=n*2-1;j+=2)
 81     {/*其他三角形与第四个三角形建边*/
 82         link(s[1][n][j],s[4][n-(j/2)][1]);
 83         link(s[2][n][j],s[4][j/2+1][((j/2)+1)*2-1]);
 84         link(s[3][n][j],s[4][n][n*2-j]);
 85     }
 86 }
 87 int tree_max(int i,int limit1,int limit2)
 88 {
 89     int from=1;/*找出i的父亲。防止又走回去*/
 90     while (c[i][from]!=limit2) from++;
 91     if (f[i][from][limit1]>0) return f[i][from][limit1];/*记忆化搜索*/
 92     int l,r;
 93     if (limit1>limit2)/*建立右子树的边界*/
 94     {
 95         l=limit2+1;
 96         r=limit1;
 97     }
 98     else/*建立左子树的边界*/
 99     {
100         l=limit1;
101         r=limit2-1;
102     }
103     int lmax=0,rmax=0;
104     for (int j=1;j<=3;j++)/*枚举当前点的所有邻接点,不找到父亲,而且符合上下边界*/
105         if (j!=from && (l<=c[i][j] && c[i][j]<=r))
106             if (c[i][j]<i)/*建立左子树*/
107                 lmax=max(lmax,tree_max(c[i][j],l,i));
108             else/*建立右子树*/
109                 rmax=max(rmax,tree_max(c[i][j],r,i));
110     f[i][from][limit1]=lmax+rmax+1;
111     return f[i][from][limit1];
112 }
113 void dfs()
114 {
115     best=0;
116     for (int i=1;i<=n*n*4;i++)/*枚举所有点*/
117     {
118         int lmax=0,rmax=0;
119         for (int j=1;j<=3;j++)
120             if (c[i][j]<i)/*c[i][j]比i小,就建立左子树*/
121                 lmax=max(lmax,tree_max(c[i][j],1,i));
122             else
123                 rmax=max(rmax,tree_max(c[i][j],n*n*4,i));
124         best=max(best,lmax+rmax+1);/*别忘了加上它本身的根节点*/
125     }
126 }
127 int main()
128 {
129     
130     init();
131     make_graph();
132     dfs();
133     printf("%d\n",best);
134     return 0;
135 }

 我的代码:

  1 #include<iostream>
  2 using namespace std;
  3 #include<cstdio>
  4 #include<cstdlib>
  5 #define Njd  2000
  6 #include<cstring>
  7 #define K 5
  8 #define L 20
  9 int gra[K][L][L<<1];
 10 int edge[Njd][5];
 11 int f[Njd][K][Njd]={0};
 12 int n,ans=0;
 13 bool vis[Njd][Njd]={0};
 14 void add_edge(int a,int b)
 15 {
 16     if(!vis[a][b])
 17     {
 18         vis[a][b]=true;
 19         edge[a][++edge[a][0]]=b;
 20     }
 21     if(!vis[b][a])
 22     {
 23         vis[b][a]=true;
 24         edge[b][++edge[b][0]]=a;
 25     }
 26 }
 27 void input()
 28 {
 29     scanf("%d",&n);
 30     for(int i=1;i<=4;++i)
 31       for(int j=1;j<=n;++j)
 32         for(int k=1;k<=(2*j-1);++k)
 33         scanf("%d",&gra[i][j][k]);
 34 }
 35 void build_graph()
 36 {
 37   for(int i=1;i<=4;++i)
 38       for(int j=2;j<n;++j)
 39         for(int k=2;k<=(2*j-2);++k)
 40         {
 41             add_edge(gra[i][j][k],gra[i][j][k-1]);
 42             add_edge(gra[i][j][k],gra[i][j][k+1]);
 43                 if(k%2==0)
 44                {
 45                 add_edge(gra[i][j][k],gra[i][j-1][k-1]);
 46                }
 47                else add_edge(gra[i][j][k],gra[i][j+1][k+1]);
 48             
 49         }
 50     for(int k=1;k<=4;++k)
 51       for(int j=2;j<=(2*n-1);j+=2)
 52       {
 53           add_edge(gra[k][n][j],gra[k][n][j-1]);
 54         add_edge(gra[k][n][j],gra[k][n][j+1]);
 55         add_edge(gra[k][n][j],gra[k][n-1][j-1]);
 56       }
 57     for(int i=1;i<=n;++i)
 58     {
 59         add_edge(gra[1][i][2*i-1],gra[2][i][1]);
 60         add_edge(gra[1][i][1],gra[3][i][2*i-1]);
 61         add_edge(gra[2][i][2*i-1],gra[3][i][1]);
 62     }
 63     for(int i=1;i<=n;++i)
 64     {
 65         add_edge(gra[4][i][2*i-1],gra[2][n][2*i-1]);
 66         add_edge(gra[4][i][1],gra[1][n][2*n-(2*i-1)]);
 67         add_edge(gra[4][n][2*i-1],gra[3][n][2*n-(2*i-1)]);
 68     }
 69 }
 70 int memory_dfs(int k,int limit1,int limit2)
 71 {
 72     int from=1;
 73     while(edge[k][from]!=limit2)
 74     {
 75         from++;
 76     }
 77     if(f[k][from][limit1]>0) 
 78        return f[k][from][limit1];
 79     int l,r;
 80     if(limit1>limit2)
 81     {
 82         r=limit1;l=limit2+1;
 83     }
 84     else {
 85         l=limit1;r=limit2-1;
 86     }
 87     int lmax=0,rmax=0;
 88     for(int j=1;j<=3;++j)
 89     {
 90         if(j!=from&&edge[k][j]>=l&&edge[k][j]<=r)
 91         {
 92             if(edge[k][j]<k)
 93             lmax=max(lmax,memory_dfs(edge[k][j],l,k));
 94             else rmax=max(rmax,memory_dfs(edge[k][j],r,k));
 95         
 96         }
 97         
 98     }
 99     f[k][from][limit1]=lmax+rmax+1;
100     return f[k][from][limit1];
101 }
102 int main()
103 {
104     input();
105     build_graph();
106     ans=0;
107     int lmax=0,rmax=0;
108     for(int i=1;i<=n*n*4;++i)
109     {
110         lmax=0;rmax=0;
111         for(int j=1;j<=3;++j)
112         {
113             if(edge[i][j]>0&&edge[i][j]<i)
114               lmax=max(lmax,memory_dfs(edge[i][j],1,i));
115             else rmax=max(rmax,memory_dfs(edge[i][j],n*n*4,i));
116         }
117         ans=max(ans,lmax+rmax+1);
118     }
119     printf("%d\n",ans);
120     return 0;
121 }

 

转载于:https://www.cnblogs.com/c1299401227/p/5576903.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/490516.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

窥探当今AI芯片中的类脑模型

来源&#xff1a;脑人言撰文丨邓 磊&#xff08;加州大学-圣塔芭芭拉分校UCSB 博士后&#xff09;责编丨高茂森 Soma排版丨夏獭科学研究的动机&#xff0c;并非仅仅是出于能看到多酷炫的应用&#xff0c;而是因为我们尚有诸多未知世界需要探寻&#xff0c;这是一切应用的前提。…

mysql调优_MYSQL企业常用架构与调优经验分享

一、选择Percona Server、MariaDB还是MYSQL1、Mysql三种存储引擎MySQL提供了两种存储引擎&#xff1a;MyISAM和 InnoDB&#xff0c;MySQL4和5使用默认的MyISAM存储引擎。从MYSQL5.5开始&#xff0c;MySQL已将默认存储引擎从MyISAM更改为InnoDB。MyISAM没有提供事务支持&#xf…

SpringMVC学习--参数绑定

spring参数绑定过程 从客户端请求key/value数据&#xff0c;经过参数绑定&#xff0c;将key/value数据绑定到controller方法的形参上。springmvc中&#xff0c;接收页面提交的数据是通过方法形参来接收。而不是在controller类定义成员变更接收。 默认支持的类型直接在controll…

现代物理学7大经典问题,你能理解几个?或许一个都不能理解

来源&#xff1a;搜狐新闻算法与数学之美相对论相对论是物理学中两大著名理论之一&#xff0c;两者都是阿尔伯特爱因斯坦提出的。1905年爱因斯坦出版了狭义相对论&#xff0c;后者确定最终宇宙速度极限&#xff1a;光速。并称时间因某物体移动的速度而实现加速或者减慢。1916年…

unity asset store下载不了_Unity手游实战:从0开始SLG——资源管理系统-基础篇(三)AssetBundle原理...

先用一句话介绍一下AssetBundle吧。AssetBundle系统提供了一种压缩文件的格式&#xff0c;可以把1到多个文件进行索引和序列化。Unity项目在交付安装之后&#xff0c;会通过AssetBundle对不包含代码的资源进行更新。这就允许开发人员先提交一个小的应用程序包&#xff0c;将运行…

matlab中GUIDE的UItable居中方法

需要借助JAVA&#xff0c;代码示意如下&#xff1a; import javax.swing.*; %导入javax.swing类 table findjobj(handles.uitable1); %需要findjobj.m文件&#xff0c;matlab中是没有的 table1 get(table,Viewport); jtable get(table1,View); renderer jtable.getCellRe…

MySQL Workbench运行脚本

首先在SCHEMAS区域右击&#xff0c;选择创建“create schema” 填入自定义名称&#xff0c;点击“apply” 在弹出来的框中点击“apply”&#xff0c;再在弹出来的框中点击finish 点击菜单栏“file”——“run SQL script”&#xff0c;选择sql文件&#xff0c;在下面选择刚刚创…

自动驾驶事故权威揭秘:算法和软件错误太多

本文来源&#xff1a;AutoR智驾自动驾驶发展就好比是登月计划。从传感器到人工智能&#xff0c;经典的电子供应链已经形成了一个协作矩阵&#xff0c;致力于实现自动驾驶车辆的安全性。为此&#xff0c;还需进行大量硬件和软件开发工作&#xff0c;以确保驾驶员、乘客和行人受到…

MySQL新建数据库和表

首先在MySQL Workbench上&#xff08;如果没有的话建议安装一个&#xff09;新建一个数据库 首先在SCHEMAS区域右击&#xff0c;选择创建“create schema” 填入自定义名称&#xff0c;点击“apply”&#xff0c;这里我命名为crashcourse 在弹出来的框中点击“apply”&#xf…

【微读书】《人工智能颠覆未来战争》连载之一:机器战胜人类?——AlphaGo人机对战的启示...

来源&#xff1a;中国指挥与控制学会编者按目前&#xff0c;人工智能技术正加速向军事领域渗透&#xff0c;军事智能化既面临千载难逢的发展机遇&#xff0c;也面临前所未有的挑战。如何加强风险研究和预判&#xff0c;防范重大风险&#xff0c;已经客观而现实地摆在我们面前。…

《崛起的超级智能》入选中国好书2019年7月榜单

来源&#xff1a;中国好书中国好书评选活动由中国图书评论学会主办&#xff0c;旨在通过好书推介传递正能量&#xff0c;推动和引导全民阅读。中国图书评论学会是由中宣部出版局创办、国家新闻出版广电总局主管的国家一级学会。自2014年举办首届年度好书盛典至今&#xff0c;“…

.net函数查询_SQL查询语句总是先执行SELECT?你们都错了!

很多 SQL 查询都是以 SELECT 开始的。不过&#xff0c;最近我跟别人解释什么是窗口函数&#xff0c;我在网上搜索”是否可以对窗口函数返回的结果进行过滤“这个问题&#xff0c;得出的结论是”窗口函数必须在 WHERE 和 GROUP BY 之后&#xff0c;所以不能”。于是我又想到了另…

大数据世界要熟悉的5门语言

大数据世界要熟悉的5门语言课程 Python OpenStack Java Hadoop Scala Spark Shell Linux SQL DB JS 华丽分割线 转载于:https://www.cnblogs.com/TendToBigData/p/10501438.html

知识图谱嵌入(KGE):方法和应用的综述

来源&#xff1a;专知导读本文主要是参考《Knowledge Graph Embedding: A Survey of Approaches and Applications》和刘知远的《知识表示学习的研究与进展》做的总结&#xff0c;主要介绍了最近关于知识图谱嵌入所涉及到的研究方法&#xff0c;主要从融合事实信息、融合附加信…

支持向量机matlab代码程序_支持向量机(SVM)小结

什么是SVM&#xff1f;SVM(全称&#xff1a;Support Vector Machine)支持向量机&#xff0c;这只是它的名称&#xff0c;向量就是和我们以前学过的向量一样(下文有介绍)&#xff0c;它可以有效解决分类问题(我们只讨论分类问题)&#xff0c;何为分类呢&#xff1f;顾名思义&…

俄罗斯拟明年在36万台华为平板安装“极光”操作系统

来源&#xff1a;环球时报据路透社报道&#xff0c;有消息人士表示&#xff0c;俄罗斯政府已经开始与华为公司就36万台平板电脑安装俄罗斯自己研发的操作系统&#xff08;OS&#xff09;"极光"(Aurora&#xff0c;也称奥罗拉)的一项计划展开谈判。路透社表示&#xf…

mysql 命令 kill_MySQL之死锁检测

最近&#xff0c;笔者在查看线上服务日志时&#xff0c;发现spring大量异常&#xff0c;异常中都显示了同样的报错信息&#xff0c;信息如下。Deadlock found when trying to get lock; try restarting transaction调研之后发现是mysql发生了死锁&#xff0c;这也是笔者第一次遇…

干货丨清华大学天机芯团队赵明国:《基于自然动力学的机器人控制——无人驾驶自行车及被动行走》...

来源&#xff1a; 机器人大讲堂8月1日&#xff0c;清华大学依托精密仪器系的类脑计算研究中心施路平教授团队在《自然》&#xff08;Nature&#xff09;杂志上发表了一篇封面文章&#xff0c;发布了一项最新研究成果——类脑计算芯片“天机芯”。同时&#xff0c;搭载天机芯&am…

判断随机抽取代码_问卷调查:定量研究中的抽样问题(2)- 非随机抽样介绍

所谓抽样&#xff0c;就是从我们需要研究的所有目标群体中&#xff0c;按照某种原则&#xff0c;挑选出一定量的样本&#xff0c;用他们的研究结果&#xff0c;代表目标群体整体结果。既然&#xff0c;抽样的目的是通过对一部分被选择的样本来推断总体&#xff0c;就要求我们抽…

欧洲估值最高的5家人工智能创业公司

来源&#xff1a;资本实验室今年初&#xff0c;据伦敦风险投资公司MMC的调查&#xff0c;四成自称为人工智能公司的欧洲创业公司实际上并未在核心业务中涉及到人工智能&#xff0c;人工智能仅为吸引投资的漂亮外衣。这一数据发布后&#xff0c;激起了轩然大波&#xff0c;不仅引…