=m-1;ifx>a[m]thens:
=m+1;
end;exit(0);end;
六、树
树的三种遍历
procedurefront(i:
integer);
begin
ift[i].name<>'#'thenbegin
write(t[i].name);
ift[i].Left<>0thenfront(t[i].Left);
ift[i].right<>0thenfront(t[i].right);
end;end;
先序中序确定后序
varsx,sz:
string;{算法}
procedurework(sx,sz:
string);{sx:
先序序列;sz:
中序序列}
varL,k:
integer;
begin
ifsx<>''then
begin
L:
=Length(sx);k:
=pos(sx[1],sz);
work(copy(sx,2,k-1),copy(sz,1,k-1));{
work(copy(sx,k+1,L-k),copy(sz,k+1,L-k));
write(sx[1]);
end;end;
begin
readLn(sx);readLn(sz);work(sx,sz);end;
哈夫曼树
procedurehufm(vartree:
treetype);
functionmin(h:
integer):
integer;{在前h个结点中选择父指针为0且权值最小的结点min}
varm1,p,i:
integer;
begin
m1:
=32767;
forp:
=1tohdo
if(tree[p].prt=0)and(m1>tree[p].data){没有父亲结点且较小的结点}
thenbegin
i:
=p;m1:
=tree[p].data;end;
min:
=i;end;
begin
fork:
=n+1tomdo{构造最优二叉树生成n-1个新结点}
begin{计算k为根的左儿子和右儿子}
i:
=min(k-1);tree[i].prt:
=k;tree[k].Lch:
=i;
j:
=min(k-1);tree[j].prt:
=k;tree[k].rch:
=j;
tree[k].data:
=tree[i].data+tree[j].data;
end;end;
七、动态规划
背包问题
原始问题:
已知背包总容量和k个物件的体积和价值。
物件要末装入背包要末不装入。
求价值和最大的装入方案。
一般方法:
阶段i:
按照递增顺序枚举物件数i;
状态j:
在不超过背包总容量的前提下,按递减顺序枚举前i件物件的可能体积j;
决策:
要使得价值和最大,第i个物件装还是不装
子序列左右取数问题
阶段l:
序列长度(1≤l≤n);状态i:
当前序列的首指针(1≤i≤n+1-l);
由此得出当前序列为[i,j](j=i+l-1)
f[i,j]为取子序列g[i,j]的最优解。
决策有两个
左端取数:
f[i+1,j]+g[i]
右端取数:
f[i,j-1]+g[j]
显然
f[i,i]=g[i]*取1个数的价值
f[i,j]=max{f[i+1,j]+g[i],f[i,j-1]+g[j]}*取1个数的价值
阶段l:
子序列长度(2≤l≤n)
状态i:
子序列首指针(1≤i≤n-l+1),子序列尾指针j=i+l-1
决策:
取i位置的数还是j位置的数
递增子序列
在数列中寻求未必连续的最长递增子序列。
例如
324456
递增子序列:
34456或者24456
一般方法:
设b[i]为前i个数中最长递增子序列的长度
阶段i:
按照递增方向枚举子序列长度(1≤i≤n)
状态j:
前一个个数的可能位置(1≤j≤i-1)
决策:
若(a[i]>a[j])and(b[j]+1>b[i])则b[i]设为b[j]+1;否则b[i]不变。
另外,可以采用二分法。
左右子序列合并
阶段l:
区间长度(2≤l≤n)
状态i:
区间首元素指针(1≤i≤n),即区间为[i,(i+l-2)modn+1]
决策k:
左子区间的尾指针k((i-1)modn+1≤k≤(i+l-3)modn+1),即左子区间为[i,k],右子区间为[(k+1)modn+1,(i+l-2)modn+1],
最后枚举尾指针为i、长度为n的所有可能区间[imodn+1),i](1≤i≤n)从中找出最佳合并方案。
指定合并次数
阶段p:
当前子序列划分出的部分数(1≤p≤m-1)
状态(i,j):
当前子序列的首尾指针(1≤i≤n,i≤j≤n);
决策k:
第p部分的首指针在什么位置时最佳(i+p≤k≤j);
注意:
当i≠1或者j≠n时,总有一部分跨过an、a1,因此先对前m-1部分进行规划,最后处理m部分的最佳划分问题。
圆排列的活动方案计数
n个元素组成一个圆排列,一次活动在相邻两元素间进行。
在指定活动m次内完成一周的传递共有多少种方案?
阶段i:
传递次数,1≤i≤m
状态j:
第i次传递到的元素序号,1≤j≤n。
注意圆排列的特殊情况:
即元素1的左右元素序号为n和2。
决策:
第i次传球时元素j接到来自左右邻的信息;
设f[i,j]为第i次传递,信息传到元素j的方案数。
显然最初信息掌握在初始元素,即f[0,初始元素序号]=1,目标是计算f[m,初始元素序号]
八、图论
图的遍历
proceduredfs(i:
longint);
varj:
longint;
begin
write(t[i],'');v[i]:
=true;
forj:
=1tondo
if(notv[j])and(a[i,j]=1)thendfs(j);
end;
procedurebfs(i:
longint);
var
q:
array[1..map]oflongint;head,tail,j:
longint;
begin
fillchar(q,sizeof(q),0);head:
=0;tail:
=1;
q[1]:
=i;v[i]:
=true;write(t[i],'');
whileheadbegininc(head);
forj:
=1tondo
if(notv[j])and(a[q[head],j]=1)thenbegin
inc(tail);q[tail]:
=j;write(t[j],'');v[j]:
=true;end;
end;end;
拓扑排序
proceduretopsort;
vari,j,k:
longint;
begin
fori:
=1tondo
begin
j:
=1;while(j<=n)and(into[j]<>0)doinc(j);
ifj=n+1thenbeginf:
=false;exit;end
elsebegin
inc(t);d[t]:
=j;into[j]:
=$fF;
fork:
=1tondoifa[j,k]=1thendec(into[k]);
end;end;end;
哈密顿路(哈密顿回路)
proceduredfs(i:
longint);
varj:
longint;
begin
visited[i]:
=true;m:
=m+1;b[m]:
=i;
if(m=n)and(a[b[n],b[1]=1)thenbegin
fori:
=1tondowrite(b[i],'');halt;end;
forj:
=1tondo
if(notvisited[j])and(a[j,i]=1)thendfs(j);
m:
=m-1;visited[i]:
=false;
end;
begin
fori:
=1tondo
beginfillchar(visited,sizeof(visited),false);m:
=0;dfs(i);end;
end.
Floyed
procedureinit;
vari,j:
longint;
begin
fori:
=1tondo
forj:
=1tondo
beginread(cost[i,j]);
if(cost[i,j]=0)or(cost[i,j]=-1)then
begincost[i,j]:
=maxint;p[i,j]:
=0;end;
a[i,j]:
=cost[i,j];
end;end;
procedurefloyed;
vari,j,k:
longint;
begin
fork:
=1tondofori:
=1tondoforj:
=1tondo
if(a[i,k]+a[k,j]a[i,j]:
=a[i,k]+a[k,j];p[i,j]:
=k;
end;end;
procedurepath(i,j:
longint);
vark:
longint;
begin
k:
=p[i,j];ifk<>0thenbegin
path(i,k);write(k,'');path(k,j);end;end;
begin
readln(n,x,y);init;floyed;writeln(a[x,y]);
ifp[x,y]=0thenwriteln('NoRoad')
elsebeginwrite(x,'');path(x,y);writeln(y);end;
end.
Dijkstra
proceduredijkstra;
vari,j,min,minj:
longint;
begin
fillchar(mark,sizeof(mark),false);
fori:
=1tondod[i]:
=maxlongint;d[k]:
=0;
fori:
=1tondo
begin
min:
=maxlongint;
forj:
=1tondo
if(notmark[j])and(d[j]min:
=d[j];minj:
=j;end;
mark[minj]:
=true;
forj:
=1tondo
if(notmark[j])and(a[minj,j]>0