/*
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 排序二叉树的更多相关文章

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

    codevs 2241 排序二叉树 ★   输入文件:bstree.in   输出文件:bstree.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] 一个边长为n的正三 ...

  2. C++11 智能指针unique_ptr使用 -- 以排序二叉树为例

    用智能指针可以简化内存管理.以树为例,如果用普通指针,通常是在插入新节点时用new,在析构函数中调用delete:但有了unique_ptr类型的智能指针,就不需要在析构函数中delete了,因为当u ...

  3. 数据结构与算法系列研究五——树、二叉树、三叉树、平衡排序二叉树AVL

    树.二叉树.三叉树.平衡排序二叉树AVL 一.树的定义 树是计算机算法最重要的非线性结构.树中每个数据元素至多有一个直接前驱,但可以有多个直接后继.树是一种以分支关系定义的层次结构.    a.树是n ...

  4. c++(排序二叉树线索化)

    前面我们谈到了排序二叉树,还没有熟悉的同学可以看一下这个,二叉树基本操作.二叉树插入.二叉树删除1.删除2.删除3.但是排序二叉树也不是没有缺点,比如说,如果我们想在排序二叉树中删除一段数据的节点怎么 ...

  5. c++(排序二叉树删除)

    相比较节点的添加,平衡二叉树的删除要复杂一些.因为在删除的过程中,你要考虑到不同的情况,针对每一种不同的情况,你要有针对性的反应和调整.所以在代码编写的过程中,我们可以一边写代码,一边写测试用例.编写 ...

  6. c++(排序二叉树)

    前面我们讲过双向链表的数据结构.每一个循环节点有两个指针,一个指向前面一个节点,一个指向后继节点,这样所有的节点像一颗颗珍珠一样被一根线穿在了一起.然而今天我们讨论的数据结构却有一点不同,它有三个节点 ...

  7. JavaScript实现排序二叉树的相关算法

    1.创建排序二叉树的构造函数 /** * 创建排序二叉树的构造函数 * @param valArr 排序二叉树中节点的值 * @constructor */ function BinaryTree(v ...

  8. Java编程的逻辑 (42) - 排序二叉树

    本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...

  9. (原创)像极了爱情的详解排序二叉树,一秒get

    排序二叉树(建立.查找.删除) 二叉树我们已经非常熟悉了,但是除了寻常的储存数据.遍历结构,我们还能用二叉树做什么呢? 我们都知道不同的遍历方式会对相同的树中产生不同的序列结果,排序二叉树就是利用二叉 ...

随机推荐

  1. ONVIF Event消息解析(How to work with gSoap)

    Prepare Requirements ONVIF Event gSoap reference ONVIF Specification 问题描述 Event是ONVIF核心规范中一块, 文档解释了如 ...

  2. [转]Python中的with…as…

    先说明一个常见问题,文件打开: 1 2 3 4 5 6 7 try:     f = open('xxx')     do something except:     do something fin ...

  3. oracle之分组内的字符串连接

    实现效果: 例如下面的数据[php] groupid        personid        name 1          a          超级管理员2          b       ...

  4. Yii2的相关学习记录,下载Yii2(一)

    原先学习过Yii1的相关知识,虽然也是半懂不懂的,但稍微的结构是了解的.现在利用晚上的时间学习下Yii2的使用,打算建一个后台管理系统,这里记录下,以免自己以后忘记. 目前已看一部分Yii2的权威指南 ...

  5. 文成小盆友python-num7 -常用模块补充 ,python 牛逼的面相对象

    本篇内容: 常用模块的补充 python面相对象 一.常用模块补充 1.configparser模块 configparser 用于处理特定格式的文件,起内部是调用open()来实现的,他的使用场景是 ...

  6. Delphi笔记(GL_Scene安装及简单使用)

    前一段时间,需要弄一个四轴的监控平台,看了匿名的上位机后,十分感兴趣.于是我也想自己也弄一个上位机来玩玩,在将串口通讯调好了以后,就开始好奇那个3D模型是怎么弄的.在网上面查找了很多资料,由于我用的是 ...

  7. android.os.NetworkOnMainThreadException 在4.0之后谷歌强制要求连接网络不能在主线程进行访问

    谷歌在4.0系统以后就禁止在主线程中进行网络访问了,原因是: 主线程是负责UI的响应,如果在主线程进行网络访问,超过5秒的话就会引发强制关闭, 所以这种耗时的操作不能放在主线程里.放在子线程里,而子线 ...

  8. VM虚拟机上 实现CentOS 6.X下部署LVS(DR)+keepalived实现高性能高可用负载均衡

    一.简介 LVS是Linux Virtual Server的简写,意即Linux虚拟服务器,是一个虚拟的服务器集群系统.本项目在1998年5月由章文嵩博士成立,是中国国内最早出现的自由软件项目之一. ...

  9. sql server 2008 case when

    CASE WHEN的两种格式 1.简单Case函数 CASE sex WHEN '1' THEN '男' WHEN '2' THEN '女' ELSE '其他' END 2.Case搜索函数 CASE ...

  10. 转:PHP教程之PHP调用session_start后页面始终加载的问题研究

    今天群里有朋友说他的遇到一个有趣的问题: 一个PHP页面的执行时间比较长(15秒左右),而只要这个页面没有执行完毕,其他的页面访问都是长时间加载状态,只有那个页面执行完毕了,剩下的页面才能打开. 这是 ...