设为首页 加入收藏

TOP

动态规划 - DP(六)
2023-07-23 13:27:39 】 浏览:134
Tags:
1;i<=n;i++) w[i]+=w[i-1]; for(int i=1;i<=n;i++) for(int j=i;j<=n;j++) p[i][j]=w[n]+w[i-1]-w[j];

状态转移:见代码

for(int i=0;i<=n;i++)
    for(int j=0;j<=n;j++)
        f[i][j][0]=f[i][j][1]=INF;
f[v][v][0]=f[v][v][1]=0;
for(int l=2;l<=n;l++)
{
    for(int i=1;i<=n-l+1;i++)
    {
        int j=i+l-1;
        if(f[i][j][0]>f[i+1][j][0]+(d[i+1]-d[i])*p[i+1][j])
            f[i][j][0]=f[i+1][j][0]+(d[i+1]-d[i])*p[i+1][j];
        if(f[i][j][0]>f[i+1][j][1]+(d[j]-d[i])*p[i+1][j])
            f[i][j][0]=f[i+1][j][1]+(d[j]-d[i])*p[i+1][j];
        if(f[i][j][1]>f[i][j-1][1]+(d[j]-d[j-1])*p[i][j-1])
            f[i][j][1]=f[i][j-1][1]+(d[j]-d[j-1])*p[i][j-1];
        if(f[i][j][1]>f[i][j-1][0]+(d[j]-d[i])*p[i][j-1])
            f[i][j][1]=f[i][j-1][0]+(d[j]-d[i])*p[i][j-1];
    }
}
if(f[1][n][0]>f[1][n][1]) printf("%d\n",f[1][n][1]);
else printf("%d\n",f[1][n][0]);

练习1:矩阵连乘

给定 \(n\) 个矩阵 \(\{ A_1, A_2, \cdots , A_n \}\),考察这 \(n\) 个矩阵的连乘积$ A_1A_2 \cdots An$ 。

由于矩阵乘法满足结合律,故计算矩阵的连乘积可以有许多不同的计算次序,

这种计算次序可以用加括号的方式来确定。矩阵连乘积的计算次序与其计算量有密切关系。

例如,考察计算 \(3\) 个矩阵$ { A_1, A_2, A_3 }$ 连乘积的例子。

设这3个矩阵的维数分别为 \(10 \times 100\)\(100 \times 5\)\(5 \times 50\)

若按 \((A1A2)A3\) 计算,\(3\) 个矩阵连乘共需要 \(10 \times 100 \times 5+10 \times 5 \times 50=7500\) 次数乘。

若按 \(A1(A2A3)\) 计算,则总共需要 \(100 \times 5 \times 50+10 \times 100 \times 50=75000\) 次数乘。

现在你的任务是给出一个矩阵连乘式,计算其需要的最少乘法次数。

练习2:矩阵取数游戏 Luogu P1005 [NOIP2007 提高组]

练习3:AtCoder Express 2 AtCoder ABC106D

练习4:玩具取名 Luogu P4290 [HAOI2008]

练习5:监狱

小X的王国中有一个奇怪的监狱,这个监狱一共有 \(P\) 个牢房,这些牢房一字排开,

\(i\) 个仅挨着第 \(i+1\) 个(最后一个除外),当然第 \(i\) 个也挨着第 \(i?1\) 个(第一个除外),

现在牢房正好是满员的。上级下发了一个释放名单,要求每天释放名单上的一个人。

这可把看守们吓得不轻,因为看守们知道,现在牢房里的 \(P\) 个人,

可以相互之间传话。第 \(i\) 个人可以把话传给第 \(i+1\) 个,当然也能传给第 \(i?1\) 个,

并且犯人很乐意把消息传递下去。

如果某个人离开了,那么原来和这个人能说上话的人,都会很气愤,

导致他们那天会一直大吼大叫,搞得看守很头疼。

如果给这些要发火的人吃上肉,他们就会安静下来。

为了河蟹社会,现在看守们想知道,如何安排释放的顺序,才能是的他们消耗的肉钱最少。

练习6:游戏 A Game Luogu P2734 [USACO3.3]

(六)双进程类动态规划

例题1:最长公共子序列

字符序列的子序列是指:

从给定字符序列中随意地(不一定连续)去掉若干个字符,

也可能一个也不去掉,去掉后所形成的字符序列为 字符序列的子序列。

令给定的字符序列\(X=\{x_0,x_1,\cdots ,x_{m-1}\}\),序列\(Y=\{y_0,y_1,\cdots ,y_{k-1}\}\)\(X\) 的子序列,

存在 \(X\) 的一个严格递增下标序列 \(\{i_0,i_1,\cdots,i_{k-1}\}\)

使得对所有的\(j=0,1,\cdots,k-1\) ,有 \(x_{ij}=y_j\)

例如,\(X=\verb!"ABCBDAB"!\)\(Y=\verb!"BCDB"!\)\(X\) 的一个子序列。

对给定的两个字符序列,求出他们最长的公共子序列长度。

状态:\(f[i][j]\)\(X\) 的前 \(i\) 位和 \(Y\) 的前 \(j\) 位所构成的最长公共子序列的长度

状态转移:\(f[i][j]=max(f[i][j-1],f[i-1][j])\)

for(int i=1;i<=len1;i++)
{
    for(int j=1;j<=len2;j++)
    {
        f[i][j]=max(f[i][j-1],f[i-1][j]);
        if(s1[i]==s2[j]&&f[i][j]<=f[i-1][j-1]) f[i][j]++;
        ans=max(ans,f[i][j]);
    }
}
printf("%d\n",ans);

例题2:配置魔药

魔药课,Snape要他们每人配置一种魔药(不一定是一样的),现在Harry面前有两个坩埚,

有许多种药材要放进坩埚里,但坩埚的能力有限,无法同时配置所有的药材。

一个坩埚相同时间内只能加工一种药材,但是不一定每一种药材都要加进坩埚里。

加工每种药材都有必须在一个起始时间和结束时间内完成

(起始时间所在的那一刻和结束时间所在的那一刻也算在完成时间内)

每种药材都有一个加工后的药效,现在要求的就是Harry可以得到最大的药效。

状态:\(f[i][j][k]\):前 \(i\) 种草药,第一个坩埚用时 \(j\),第二个坩埚用时 \(k\) 能得到的最大功效

状态转移:\(j \geq a[i].t2\) 时,\(f[j][k]=max(f[j][k],f[a[i].t1-1][k]+a[i].w)\)

? 当 \(k \geq a[i].t2\) 时,\(if(k>=a[i].t2) f[j][k]=max(f[j][k],f[j][a[i].t1-1]+a[i].w)\)

bool mycmp(node a,node b)
{
	return a.t2<b.t2;
}
for(int i=1;i<=n;i++)
    cin>>a[i].t1>>a[i].t2>>a[i].w;
sort(a+1,
首页 上一页 3 4 5 6 7 下一页 尾页 6/7/7
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Manacher算法学习笔记 下一篇现代C++学习指南-方向篇

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目