取数模型与DP
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
取数模型与DP
1、数字三角形
每行取一个(下面的位置是上面的邻居),从上往下,求最大和。
样例:
输入N=5,下面是5行数字:
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
DP方程:
a[i,j]:=max{a[i+1,j], a[i+1,j+1]}+a[i,j] (1<=i,j<=n-1)
主要程序段:for i:=n-1 downto 1 do //从倒数第二行往上做。
For j:=1 to i do
If a[i+1,j]>a[i+1,j+1] then a[i,j]:=a[i,j]+ a[i+1,j]
Else a[i,j]:=a[i,j]+ a[i+1,j+1];
Writeln(a[1,1]);
2、求环形整数串的最大连续和。P1308
输入样例
6
-2 3 0 1 -48 80
输出样例
82
线形DP:
转化成环形
分两种情况:
1、如:-2 2 0 1 -48 1,显然其最大和连续子串是2 0 1,其和是3。
选的是中间的一段,这种情况直接使用上述的线形DP公式。
2、样例:-2 3 0 1 -48 80 结果82
选的是断开处的两端,要当成环处理。
怎样处理第2种情况呢?
第2种情况可以找中间连续一段最小的值,然后拿所有数的和--最小值
DP方法:在上页DP方程的基础上,
Ans=MAX(线性DP最大值, sum-线性DP最小值);
N值很大,如果超过数组能定义的范围,可以不用数组保存这N个数,
而是直接读一个数就处理一次。
3、求最长不下降序列P1194
样例:[输入] 14 {表示14个数}
13 7 9 16 38 24 37 18 44 19 21 22 63 15
[输出] 8 {长度为8}
7 9 16 18 19 21 22 63 {其中一种取法}
从前往后,每选一个数,总可以得到此时的最长序列,这一段的最长序列不会因为后面的不同取数方法而改变,故无后效性。
DP方程为:F[i]=MAX(F[1],………,F[i-1],其中所项的一项必须能与F[i]相连接)+1。
4、求两串字符的最长公共子序列
[输入样例]
A BC
B D A B
B D
C A BA
[输出样例]
4
BCBA
样例:C[4,5] 因为x[4]= y[5],所以c[4,5]=c[3,4]+1
C[5,4] 因为x[5]<> y[4],所以c[5,4]=max{c[5,3], c[4,4]}
最后输出C[7,6]的值。
用c[i,j]记录序列Xi和Yj的最长公共子序列的长度。C[i,j]的值表示:取X列的前i个字母,取y列的前j个字母得到的公共最长子序列的长度。边界:当i=0或j=0时,c[i,j]=0。
for i:=1 to length(x) do
for j:=1 to length(y) do
if x[i]=y[j] then c[i,j]:=c[i-1,j-1]+1
else if c[i-1,j]>c[i,j-1] then c[i,j]:=c[i-1,j] else c[i,j]:=c[i,j-1];5、求三串中的最长公共子串。P1338 胖男孩
var sol:array[0..100,0..100,0..100]of string[100];
sa,sb,sc:string[1la,lb,lc:integer;
procedure work;
var i,j,k:integer; max:string;
begin
for i:=1 to la do
for j:=1 to lb do
for k:=1 to lc do
begin
max:=''; sol[i,j,k]:='';
if length(sol[i-1,j,k])>length(max) then max:=sol[i-1,j,k];
if length(sol[i,j-1,k])>length(max) then max:=sol[i,j-1,k];
if length(sol[i,j,k-1])>length(max) then max:=sol[i,j,k-1];
if length(sol[i-1,j-1,k])>length(max) then max:=sol[i-1,j-1,k];
if length(sol[i-1,j,k-1])>length(max) then max:=sol[i-1,j,k-1];
if length(sol[i,j-1,k-1])>length(max) then max:=sol[i,j-1,k-1];
if (sa[i]=sb[j])and(sb[j]=sc[k])and (( length(sol[i-1,j-1,k-1]+sa[i]) ) >length(max))then max:=sol[i-1,j-1,k-1]+sa[i];
sol[i,j,k]:=max;
end;
end;
begin
readln(sa);
readln(sb);
readln(sc);
la:=length(sa);
lb:=length(sb);
lc:=length(sc);
work;
writeln(length(sol[la,lb,lc]));
end.
6、机器分配P1029
M个数N个人取,取不同的数得到的代价不同,怎样取,代价最大。
3 2 // 3个数,2个人取
1 2 3 //第一个人取1 2 3个数的代价
2 3 4 //第二个人取1 2 3个数的代价
输出:4
方案一:第一个人取2个数,代价2,第二个人取1个数,代价2,总和是4
方案二:第一个人取3个数,代价3
方案三:第一个人取1个数,代价1,第二个人取2个数,总和是4
。。。。
虽然方案很多,但最大代价和是4固定的。
用A[i,j]保存下面的N行数据。
F[i,j]表示第i个人取j台的最大价值。
能否用前面的状态来表示呢?
如F[2,3]表示2个公司分配3台的最大价值。可以用什么来表示?
F[1,0]+A[2,3]