DP动态规划
DP动态规划

DP动态规划

状压DP

状态压缩的思想是用二进制来表示状态。用一个整数的二进制形式的每一个二进制位 0 或 1 表示一个状态。

状压DP的时间复杂度为 O(n^2*2^n),通常只能通过 N≤21 的数据范围,本题数据范围为 N≤15 因此可以使用状压DP。

题目描述

房间里放着 n 块奶酪。一只小老鼠要把它们都吃掉,问至少要跑多少距离?老鼠一开始在 (0,0) 点处。
输入格式

第一行有一个整数,表示奶酪的数量 n。

第 2 到第 (n+1) 行,每行两个实数,第 (i+1) 行的实数分别表示第 i 块奶酪的横纵坐标 xi​,yi​。
输出格式

输出一行一个实数,表示要跑的最少距离,保留 2 位小数。

定义一个数组 Fi,j,表示老鼠走到第 i 个奶酪,且走过的二进制状态为 j 时,最短的距离。

举例来说,可以使用二进制 10100110 来表示已经走过第 2、3、6、8 个奶酪,此时 j 的值为 166。需要注意的是,第 i 个状态是从低位向高位的第i位。

首先要将 F 数组进行初始化为极大值,可以使用memset(F,127,sizeof(F));来为浮点数赋极大值

因为到达第 i 块奶酪,且只经过过第 i 块奶酪的距离即为第i块奶酪与坐标原点的距离。因此要初始化F[i][(1<<(i-1))]=a[0][i];。

三层循环:

第一层:
枚举出范围内所有二进制数,以便后面的转换。

第二层:

枚举1–n,判断是否走过第i块奶酪,如果没有走过,直接跳过。

第三层:

同样枚举1–n,判断在i块奶酪前是否还走过别的奶酪,如果没有走过,直接跳过。

如果走过,则进入转换

接下来就可以转移状态了:

设此时二进制状态为 k,终点为 i,起点为 j,可得状态转移方程:Fi,k=min(Fi,k,Fj,k−2i−1+Ai,j)。Fj,k−2i−1 为在 j 点且没有走过 i 点的最短距离, Ai,j 是从 i 到 j 的距离。

F[i][k]=min(F[i][k],F[j][k-(1<<(i-1))]+a[i][j]);

最后,找出 Fi,2N−1 中的最小值就是最终的答案了。

相关条目

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注