22.4.6

news/2025/2/12 19:56:00/

1,二叉树四种遍历,2,string 去重(去空格)3,根据二叉树后序和中序,求先序;4,已知二叉树后序和中序,求层序;5,蒙德里安的梦想(状态压缩dp)


void InorderTraversal( BinTree BT )//中序
{if(BT==NULL)return;InorderTraversal(BT->Left);printf(" %c",BT->Data);InorderTraversal(BT->Right);
}
void PreorderTraversal( BinTree BT )//先序
{if(BT==NULL)return;printf(" %c",BT->Data);PreorderTraversal(BT->Left);PreorderTraversal(BT->Right);
}
void PostorderTraversal( BinTree BT )//后序
{if(BT==NULL)return;PostorderTraversal(BT->Left);PostorderTraversal(BT->Right);printf(" %c",BT->Data);
}
void LevelorderTraversal( BinTree BT )//层序
{BinTree temp[1100];int in=0;int out=0;temp[in++]=BT;while(in>out){if(temp[out]){printf(" %c",temp[out]->Data);temp[in++]=temp[out]->Left;temp[in++]=temp[out]->Right;}out++;}
}
void PreorderPrintLeaves( BinTree BT )//先序输出叶子节点
{if(BT){if(!BT->Left&&!BT->Right)printf(" %c",BT->Data);PreorderPrintLeaves(BT->Left);PreorderPrintLeaves(BT->Right);}
}

2,去空格

	rep1(i,0,n){if(s1[i]==' ')s1.erase(i,1);if(s2[i]==' ')s2.erase(i,1);}

erase(x,len)是从x位置开始,删去len长度;


函数调用中,对数组加一个常数的操作时对数组进行裁剪?

 


3,知中序,后序求先序;

#include<bits/stdc++.h>
#define rep1(i,a,n) for(register int i=a;i<n;i++) 
#define rep2(i,a,n) for(register int i=a;i<=n;i++) 
#define per1(i,n,a) for(register int i=n;i>a;i--) 
#define per2(i,n,a) for(register int i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define INF 0x3f3f3f3f
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
int n;
int post[10000],mid[10000];
void dfs(int *post,int *mid,int x)
{if(x>0){int root;root=post[x-1];cout<<" "<<root;	rep1(i,0,x){if(root==mid[i]){dfs(post,mid,i);dfs(post+i,mid+i+1,x-i-1);return;}}}
}
signed main()
{quick_cin();cin>>n;rep1(i,0,n)cin>>post[i];rep1(i,0,n)cin>>mid[i];cout<<"Preorder:";dfs(post,mid,n);return 0;
}

4,求层序

试着直接改编3,的板子,来求层序,但是实现的话比较麻烦,还不如直接利用先序来建个树,对树求层序就比较简单了,当然,3,也可以这样做,先求树,再求先序,但我毕竟是根据先序键树的,能直接输出先序,就不用建树了;

所以既然是根据先序建树,那我可以直接用3,的板子,稍作修改就可;

主要是dfs,新增两个参数,一个是用来建树用到的父节点,一个是区分左右节点的char类型;

还是比较好写的;

void dfs(int *post,int *mid,int x,int father,char c)
{if(x>0){int root=post[x-1];if(c=='l')pp[father].first=root;if(c=='r')pp[father].second=root;rep1(i,0,x){if(root==mid[i]){dfs(post,mid,i,root,'l');dfs(post+i,mid+i+1,x-i-1,root,'r');return;}}}
}
#include<bits/stdc++.h>
#define rep1(i,a,n) for(register int i=a;i<n;i++) 
#define rep2(i,a,n) for(register int i=a;i<=n;i++) 
#define per1(i,n,a) for(register int i=n;i>a;i--) 
#define per2(i,n,a) for(register int i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define INF 0x3f3f3f3f
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
int n;
const int N=1e3+10;
int post[10000],mid[10000];
queue<int>q;
PII pp[N];
void dfs(int *post,int *mid,int x,int father,char c)
{if(x>0){int root=post[x-1];if(c=='l')pp[father].first=root;if(c=='r')pp[father].second=root;rep1(i,0,x){if(root==mid[i]){dfs(post,mid,i,root,'l');dfs(post+i,mid+i+1,x-i-1,root,'r');return;}}}
}
signed main()
{quick_cin();cin>>n;rep1(i,0,n)cin>>post[i];rep1(i,0,n)cin>>mid[i];dfs(post,mid,n,post[n-1],'0');q.push(post[n-1]);cout<<post[n-1];while(q.size()){int t=q.front();if(t!=post[n-1])cout<<" "<<t;q.pop();if(pp[t].first)q.push(pp[t].first);if(pp[t].second)q.push(pp[t].second);}return 0;
}

5,蒙德里安的梦想

 题意:

核心:(数据范围很小,可以用二进制数表示状态)

先放横着的,在放竖着的 ;这样只要我横着放完,剩下的竖的只要嵌进去就行,所以竖着的只能是这样,即总方案数是横着放的合法方案数;如何判断方案是否合法呢,只需要判断每一列剩下的连续空棋盘数是否为偶数,偶数则合法,否则不合法;

按照闫式dp分析法:

第一步:状态表示:
f[ i , j ] 表示 前i-1列已经放好,从第 i-1 列伸到第 i 列的状态是 j 的所有方案;

属性:数量;

第二步:状态计算:

因为属性是数量,所以f[ i , j ]是所有子集方案之和;

先划分集合:

对于每一行,都有伸或者不伸到第i列两种选择,所以共2^n种方案;

这样划分也是不重不漏的;

这里是表示状态是可以状态压缩的,用个长度为n的二进制数,eg:01000...;表示第二行 伸到第i列,而其他所有行都不伸到第i列的一种方案;

划分好子集后,需要去求子集,进而才能求f[ i , j  ],也就是找状态转移;

既然第 i 列固定了,我们需要看 第i-2 列是怎么转移到到第 i-1列的(看最后转移过来的状态)。假设此时对应的状态是k(第i-2列到第i-1列伸出来的二进制数,比如00100),k也是一个二进制数,1表示哪几行小方块是横着伸出来的,0表示哪几行不是横着伸出来的。

它刚好就是f[ i -1 ,  k ] , 但是,这个k是有条件限制的,也就是需要是合法的方案;

①k和j不能在同一行,即j&k==0,原因:因为从i-1列到第i列是横着摆放的12的方块,那么i-2列到i-1列就不能是横着摆放的,否则就是1 3的方块了!这与题意矛盾。所以 k和j不能位于同一行!

既然从第i-1列到第i列横着摆的,和第i-2列到第i-1列横着摆的都确定了,那么第i-1列 空着的格子就确定了,这些空着的格子将来用作竖着放。如果 某一列有这些空着的位置,那么该列所有连续的空着的位置长度必须是偶数。

满足这两个条件,f[ i ][ j ] += f[ i-1 ][ k ]; 

对这两个条件直接全部枚举可能会tle,这里优化下对条件的筛选;

#include<bits/stdc++.h>
#define rep1(i,a,n) for(register int i=a;i<n;i++) 
#define rep2(i,a,n) for(register int i=a;i<=n;i++) 
#define per1(i,n,a) for(register int i=n;i>a;i--) 
#define per2(i,n,a) for(register int i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define INF 0x3f3f3f3f
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
int n,m;
const int N=12,M=1<<N;
ll f[N][M];
vector<int>state[M];
bool st[M];
signed main()
{quick_cin();while(cin>>n>>m,n||m){//第一部分:预处理1//对于每种状态,先预处理每列不能有奇数个连续的0rep1(i,0,1<<n){int cnt=0;//记录连续的0的个数bool isvalid=1;// 某种状态没有奇数个连续的0则标记为truerep1(j,0,n)//遍历这一列,从上到下{if(i>>j&1)//i>>j位运算,表示i(i在此处是一种状态)的二进制数的第j位; &1为                        //判断该位是否为1,如果为1进入if{if(cnt&1)//这一位为1,看前面连续的0的个数,如果是奇数(cnt &1为真)则该                                                        状态不合法{isvalid=0;break;}cnt=0;// 既然该位是1,并且前面不是奇数个0(经过上面的if判断),计数器清                                         零。//其实清不清零没有影响}else cnt++;}if(cnt&1)isvalid=0;st[i]=isvalid;//状态i是否有奇数个连续的0的情况,输入到数组st中}//下面来看进一步的判断:看第i-2列伸出来的和第i-1列伸出去的是否冲突rep1(j,0,1<<n) //对于第i列的所有状态{state[j].clear(); //清空上次操作遗留的状态,防止影响本次状态。rep1(k,0,1<<n)//对于第i-1列所有状态{if((j&k)==0&&st[j|k])state[j].pb(k); // 第i-2列伸出来的 和第i-1列伸出来            的不冲突(不在同一行) //解释一下st[j | k] //已经知道st[]数组表示的是这一列没有连续奇数个0的情况,//我们要考虑的是第i-1列(第i-1列是这里的主体)中从第i-2列横插过来的,还要考         虑自己这一列(i-1列)横插到第i列的//比如 第i-2列插过来的是k=10101,第i-1列插出去到第i列的是 j =01000,//那么合在第i-1列,到底有多少个1呢?自然想到的就是这两个操作共同的结果:两个     状态或。 j | k = 01000 | 10101 = 11101//这个 j|k 就是当前 第i-1列的到底有几个1,即哪几行是横着放格子的}}memset(f,0,sizeof f);f[0][0]=1;rep2(i,1,m)rep1(j,0,1<<n)for(auto k:state[j])f[i][j]+=f[i-1][k];cout<<f[m][0]<<endl;}return 0;
}


http://www.ppmy.cn/news/191634.html

相关文章

win10+vs2017环境中编译64位的openh264.dll库文件

一、环境配置 1、安装vs2017。 2、安装MinGW。这一步的坑是&#xff1a;在安装mingw之后还得单独下载msys压缩包&#xff0c;解压到mingw目录下 将存放make.exe的路径C:\MinGW\msys\bin配置在系统path参数里面&#xff0c;否则会找不到make命令。 3、安装nasm。 下载nas…

linux查看硬盘插槽_linux如何查看硬件信息CPU,内存,硬盘

1、 查看CPU 1.1 查看CPU个数 # cat /proc/cpuinfo | grep "physical id" | uniq | wc -l 2 //两个物理CPU **uniq命令&#xff1a;删除重复行&#xff1b;wc –l命令&#xff1a;统计行数** 1.2 查看CPU核数 # cat /proc/cpuinfo | grep "cpu cores" | un…

华大HC32A460 系列介绍(一)

[T1、华大HC32A460系列产品特性 ARM Cortex-M4 32bit MCUFPU&#xff0c;250DMIPS&#xff0c;up to 512KB Flash&#xff0c;192KB SRAM&#xff0c;USB FS&#xff08;Device/Host&#xff09;&#xff0c; 14 Timers&#xff0c;2 ADCs&#xff0c;1 PGA&#xff0c;3 CMPs&…

LCD驱动芯片(IC)-VK2C系列(VK2C21/22/23/24)多用于燃气表;水表/电气表等,具抗干扰及低功耗特性

VK2C系列&#xff0c;是点阵式存储映射的LCD驱动器&#xff0c;单片机可通过I2C接口配置显示参数和读写显示数据&#xff0c;也可通过指令进入省电模式。其高抗干扰/低功耗的特性适用于水电气表及工控仪表类。 VK2C21 特点&#xff1a; • 工作电压 2.4-5.5V • 内置32 kHz RC…

t5810做虚拟服务器,戴尔Precision T5810工作站选用CPU的问题 | 小迪的生产力工具室...

戴尔 Precision T5810 图形工作站标配的 CPU 一般都是 Intel 至强 E5-1600 系列的 CPU&#xff0c;但这并不是绝对的&#xff0c;T5810 也是支持 E5-2600 系列 CPU 的&#xff0c;这个案例就是说明这一点。 出镜产品&#xff1a; DELL Precision T5810 工作站 CPU Intel Xeon E…

3.22 66-

一.封装 1.定义 1.禁止直接访问一个对象中数据的实际表示 通过接口来访问 &#xff08;信息隐藏&#xff09; 2.属性私有 get/set 2.代码解释 1.属性私有 private 2.提供一些public 的get set方法 3.封装的意义 1.提高程序的安全性&#xff0c;保护数据 2.隐藏代码的具…

在Dell服务器PowerEdge R730上安装操作系统

实验室最近搞到了两台服务器&#xff0c;比较新鲜。本人对服务器一窍不通&#xff0c;首先学习了安装操作系统跟拆拔常见组件。慢慢熟悉服务器的操作方法。现在对服务器安装操作系统做一个总结。 安装系统之前 介绍一下测试服务器的基本配置 DELL 6核E5-2603v4 1.7GHz/8G/1T…

联盛德 HLK-W806 (六): I2C驱动SSD1306 128x64 OLED液晶屏

目录 联盛德 HLK-W806 (一): Ubuntu20.04下的开发环境配置, 编译和烧录说明联盛德 HLK-W806 (二): Win10下的开发环境配置, 编译和烧录说明联盛德 HLK-W806 (三): 免按键自动下载和复位联盛德 HLK-W806 (四): 软件SPI和硬件SPI驱动ST7735液晶LCD联盛德 HLK-W806 (五): W801开发…