codevs 2241 排序二叉树
- /*
- WTF
- 写了好久了 开始的时候题目读错了 建图建错了
- 搜索写的也不好 感觉会T
- 总之 第一次写的很low
- 贴一下吧
- */
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #define N 40
- #define M 40
- using namespace std;
- int n,g[N*N][N*N],a[][M*M];
- int num[],ans,maxx,f[N*N][N*N];
- struct node
- {
- int c[],data;
- int x[],y[];
- }p[N*N][N*N];
- int Get_place(int x,int y)
- {
- if(x<=n)return ;
- if(y>(x-n)*-&&y<=*n)return ;
- if(y<=(x-n)*-)return ;
- return ;
- }
- int Dfs(int x,int y)
- {
- int sum=;
- for(int i=;i<=;i++)
- for(int j=;j<=;j++)
- {
- if(p[x][y].c[i]<p[x][y].data&&p[x][y].c[j]>p[x][y].data
- &&f[p[x][y].x[i]][p[x][y].y[i]]==&&f[p[x][y].x[j]][p[x][y].y[j]]==)
- {
- f[p[x][y].x[i]][p[x][y].y[i]]=;f[p[x][y].x[j]][p[x][y].y[j]]=;
- sum=max(sum,Dfs(p[x][y].x[i],p[x][y].y[i])+Dfs(p[x][y].x[j],p[x][y].y[j]));
- f[p[x][y].x[i]][p[x][y].y[i]]=;f[p[x][y].x[j]][p[x][y].y[j]]=;
- }
- }
- for(int i=;i<=;i++)
- {
- if(f[p[x][y].x[i]][p[x][y].y[i]]==)
- {
- f[p[x][y].x[i]][p[x][y].y[i]]=;
- sum=max(sum,Dfs(p[x][y].x[i],p[x][y].y[i]));
- f[p[x][y].x[i]][p[x][y].y[i]]=;
- }
- }
- return sum;
- }
- int main()
- {
- scanf("%d",&n);
- for(int k=;k<=;k++)
- for(int i=;i<=n*n;i++)
- scanf("%d",&a[k][i]);
- num[]=n*n;
- for(int i=;i<=n*;i++)
- for(int j=;j<=*i-;j++)
- {
- int pi=Get_place(i,j);
- if(pi==)g[i][j]=a[pi][num[pi]--];
- else g[i][j]=a[pi][++num[pi]];
- }
- for(int i=;i<=n*;i++)
- for(int j=;j<=i*-;j++)
- {
- if(j&)
- {
- p[i][j].c[]=g[i][j-];
- p[i][j].c[]=g[i][j+];
- p[i][j].c[]=g[i+][j+];
- p[i][j].data=g[i][j];
- p[i][j].x[]=i;p[i][j].y[]=j-;
- p[i][j].x[]=i;p[i][j].y[]=j+;
- p[i][j].x[]=i+;p[i][j].y[]=j+;
- }
- else
- {
- p[i][j].c[]=g[i][j-];
- p[i][j].c[]=g[i][j+];
- p[i][j].c[]=g[i-][j-];
- p[i][j].data=g[i][j];
- p[i][j].x[]=i;p[i][j].y[]=j-;
- p[i][j].x[]=i;p[i][j].y[]=j+;
- p[i][j].x[]=i-;p[i][j].y[]=j-;
- }
- if(j==)
- {
- p[i][j].c[]=g[*n+-i][j];
- p[i][j].x[]=*n+-i;
- p[i][j].y[]=*n-*i+;
- }
- if(j==i*-)
- {
- p[i][j].c[]=g[*n+-i][*n-*i+];
- p[i][j].x[]=*n+-i;
- p[i][j].y[]=*n-*i+;
- }
- if(i==*n&&(j&))
- {
- p[i][j].c[]=g[i][*n-j];
- p[i][j].x[]=i;
- p[i][j].y[]=*n-j;
- }
- }
- //int xi,yi;
- //while(~scanf("%d%d",&xi,&yi))
- //printf("%d\n%d %d %d\n",p[xi][yi].data,p[xi][yi].c[1],p[xi][yi].c[2],p[xi][yi].c[3]);
- for(int i=;i<=n*;i++)
- for(int j=;j<=i*-;j++)
- {
- memset(f,,sizeof(f));
- f[i][j]=;ans=max(Dfs(i,j),ans);
- }
- printf("%d\n",ans);
- return ;
- }
- /*
- 换一种建图方式 这样很机智啊 然而我并没有想到
- 保留原来的三个4个三角形 然后建图 而不是搞到一个大的三角形里再建图
- 具体看代码吧
- 我们得到了每个点相邻的三个点的权值以后 需要枚举根 然后扩展结点 统计最大值
- 对于每一个点 我们并不需要分开考虑左右都选还是直选左或者直选右
- 我们左右都扩展一遍然后取大并做和就ok
- 但是介于二叉搜索树的要求 如果我们扩展节点时只要求他和相邻父亲比较大小的话
- 不能满足左子树的每个节点都小于根 所以我们扩展的时候再维护一下边界 这样的话就使得树满足性质了
- 然而时间复杂度会很大 需要记忆化
- 再然而我们这个状态不好表示 只能用3维 f[i][j][k] 表示从j到i 边界是k(不管是左还是右)以i为根的最优解
- 再再然而我们又发现这个状态爆空间了-- 降维的话 如果把第三维降掉显然会有重复
- 其实我们的j到i是很浪费的 我们可以压缩第二维 把到从j改为从i的第几个相邻的点到的
- 这样我们就能存下了 然后就是细节问题了
- 开始存小三角形用的5*20*20 n<=18 RE到死....忘记存的三角形不是矩形了.....WTF
- */
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #define N 40//数组开大保平安
- #define M 20*20*4
- using namespace std;
- int n,g[][N][N],s[M][],ans;
- bool vis[M][M];
- int f[M][][M];
- void Init()
- {
- cin>>n;
- for(int k=;k<=;k++)
- for(int i=;i<=n;i++)
- for(int j=;j<=i*-;j++)
- cin>>g[k][i][j];
- }
- void Add(int x,int y)
- {
- if(vis[x][y]==)
- {
- vis[x][y]=;
- s[x][++s[x][]]=y;
- }
- if(vis[y][x]==)
- {
- vis[y][x]=;
- s[y][++s[y][]]=x;
- }
- }
- void Build_tree()
- {
- for(int k=;k<=;k++)//内部点
- for(int i=;i<=n-;i++)
- for(int j=;j<*i-;j++)
- if(j&)
- {
- Add(g[k][i][j],g[k][i][j+]);
- Add(g[k][i][j],g[k][i][j-]);
- Add(g[k][i][j],g[k][i+][j+]);
- }
- else
- {
- Add(g[k][i][j],g[k][i][j+]);
- Add(g[k][i][j],g[k][i][j-]);
- Add(g[k][i][j],g[k][i-][j-]);
- }
- for(int k=;k<=;k++)//底边界偶数点
- for(int i=;i<=n*-;i+=)
- {
- Add(g[k][n][i],g[k][n][i+]);
- Add(g[k][n][i],g[k][n][i-]);
- Add(g[k][n][i],g[k][n-][i-]);
- }
- for(int i=;i<=n;i++)//侧边界点
- {
- Add(g[][i][*i-],g[][i][]);
- Add(g[][i][*i-],g[][i][]);
- Add(g[][i][*i-],g[][i][]);
- }
- for(int i=;i<=n*-;i+=)//底边界奇数点
- {
- Add(g[][n][i],g[][n-(i/)][]);
- Add(g[][n][i],g[][i/+][(i/+)*-]);
- Add(g[][n][i],g[][n][*n-i]);
- }
- }
- int DP(int i,int l1,int l2)//因为要用到i来自哪 所以左右边界可能颠倒
- {
- int from=;
- while(s[i][from]!=l2)from++;//i是从i的第几个相邻的点连过来的
- if(f[i][from][l1]>)return f[i][from][l1];//记忆化
- int l,r,lmax=,rmax=;
- if(l1>l2)l=l2+,r=l1;//修正左右边界
- else l=l1,r=l2-;
- for(int j=;j<=;j++)
- if(j!=from&&l<=s[i][j]&&r>=s[i][j])
- {
- if(s[i][j]<i)lmax=max(lmax,DP(s[i][j],l,i));
- else rmax=max(rmax,DP(s[i][j],r,i));
- }
- f[i][from][l1]=lmax+rmax+;
- return f[i][from][l1];
- }
- void Dfs()
- {
- for(int i=;i<=n*n*;i++)//枚举根节点
- {
- int lmax=,rmax=;
- for(int j=;j<=;j++)
- if(s[i][j]<i)lmax=max(lmax,DP(s[i][j],,i));//左子树的所有数在1-i-1之间
- else rmax=max(rmax,DP(s[i][j],n*n*,i));//右子树的所有数在i+1-n*n*4之间
- ans=max(ans,+lmax+rmax);
- }
- }
- int main()
- {
- //freopen("bstree.in","r",stdin);
- //freopen("bstree.out","w",stdout);
- Init();
- Build_tree();
- Dfs();
- cout<<ans<<endl;
- return ;
- }
codevs 2241 排序二叉树的更多相关文章
- 记忆化搜索 codevs 2241 排序二叉树
codevs 2241 排序二叉树 ★ 输入文件:bstree.in 输出文件:bstree.out 简单对比时间限制:1 s 内存限制:128 MB [问题描述] 一个边长为n的正三 ...
- C++11 智能指针unique_ptr使用 -- 以排序二叉树为例
用智能指针可以简化内存管理.以树为例,如果用普通指针,通常是在插入新节点时用new,在析构函数中调用delete:但有了unique_ptr类型的智能指针,就不需要在析构函数中delete了,因为当u ...
- 数据结构与算法系列研究五——树、二叉树、三叉树、平衡排序二叉树AVL
树.二叉树.三叉树.平衡排序二叉树AVL 一.树的定义 树是计算机算法最重要的非线性结构.树中每个数据元素至多有一个直接前驱,但可以有多个直接后继.树是一种以分支关系定义的层次结构. a.树是n ...
- c++(排序二叉树线索化)
前面我们谈到了排序二叉树,还没有熟悉的同学可以看一下这个,二叉树基本操作.二叉树插入.二叉树删除1.删除2.删除3.但是排序二叉树也不是没有缺点,比如说,如果我们想在排序二叉树中删除一段数据的节点怎么 ...
- c++(排序二叉树删除)
相比较节点的添加,平衡二叉树的删除要复杂一些.因为在删除的过程中,你要考虑到不同的情况,针对每一种不同的情况,你要有针对性的反应和调整.所以在代码编写的过程中,我们可以一边写代码,一边写测试用例.编写 ...
- c++(排序二叉树)
前面我们讲过双向链表的数据结构.每一个循环节点有两个指针,一个指向前面一个节点,一个指向后继节点,这样所有的节点像一颗颗珍珠一样被一根线穿在了一起.然而今天我们讨论的数据结构却有一点不同,它有三个节点 ...
- JavaScript实现排序二叉树的相关算法
1.创建排序二叉树的构造函数 /** * 创建排序二叉树的构造函数 * @param valArr 排序二叉树中节点的值 * @constructor */ function BinaryTree(v ...
- Java编程的逻辑 (42) - 排序二叉树
本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...
- (原创)像极了爱情的详解排序二叉树,一秒get
排序二叉树(建立.查找.删除) 二叉树我们已经非常熟悉了,但是除了寻常的储存数据.遍历结构,我们还能用二叉树做什么呢? 我们都知道不同的遍历方式会对相同的树中产生不同的序列结果,排序二叉树就是利用二叉 ...
随机推荐
- 如何遍历json属性和动态添加属性
var person= { name: 'zhangsan', pass: '123' , 'sni.ni' : 'sss', hello:function (){ for(var i=0;i< ...
- css3之box-sizing
css盒子模型中包括几种重要的属性,包括margin.border.padding以及content.但浏览器对其盒子模型的解释则有所不痛,启用标准模式还是IE(怪)模式是与当前页面的文档声明相关的. ...
- 8个不可不知的Mac OS X专用命令行工具(转)
OS X的终端下通用很多Unix的工具和脚本.如果从Linux迁移到OS X会发现很多熟悉的命令和脚本工具,其实并没有任何区别. 但是OS X也提供了很多其他系统所没有的特别的命令行工具.我们推荐8个 ...
- underscorejs-some学习
2.11 some 2.11.1 语法: _.some(list, predicate, [context]) 2.11.2 说明: 对list集合的每个成员根据predicate进行真值检测,如果一 ...
- 修改PHP的默认时区
每个地区都有自己的本地时间,在网上及无线电通信中,时间的转换问题显得格外突出.整个地球分为24个时区,每个时区都有自己的本地时间.在国际无线电或网络通信场合,为了统一起见,使用一个统一的时间,成为通用 ...
- UVA - 11346 Probability (概率)
Description Probability Time Limit: 1 sec Memory Limit: 16MB Consider rectangular coordinate system ...
- Equivalent Strings (字符串相等?)
Equivalent Strings E - 暴力求解.DFS Time Limit:2000MS Memory Limit:262144KB 64bit IO Format:%I ...
- Eclipse+Pydev +Django搭建开发环境时容易出错的几点
1.注意安装的软件和系统的位数是否匹配. 2.安装Django框架的时候注意是否安装了setuptools工具.在Python中,安装第三方模块,是通过setuptools这个工具完成的.Python ...
- Java获取程序或项目路径的常用方法
在写java程序时不可避免要获取文件的路径,比较常用的方法有: 1 在任意的class里调用: this.getClass().getClassLoader().getResource("/ ...
- 【HDOJ】2424 Gary's Calculator
大数乘法加法,直接java A了. import java.util.Scanner; import java.math.BigInteger; public class Main { public ...