“我们会死很久,所以活着的时候一定要很开|

jxy2012

园龄:1年2个月粉丝:1关注:2

[ABC232F] Simple Operations on Sequence 题解

我们把问题陈述中的第一个操作称为 "增/减",第二个操作称为 "交换"。

在这里,让我们对问题陈述稍加限制,一旦执行了增/减操作,就不能再执行交换操作。

换句话说,唯一允许的操作过程是:

  • 首先执行任意次数(可能为零)的交换;
  • 然后执行任意次数(可能为零)的递增/递减。

这一修改不会改变答案。因为 "递增/递减后交换 "可以替换为 "交换后递增/递减"。

从初始状态 A=(A1,A2,,AN) 出发,考虑 "交换任意次数 "步骤完成后的状态,其中 A 可以表示为 A=(AP1,AP2,,APN) 。这里, P=(P1,P2,,PN)1,2,3,,N 的排列。

要使 A 等于 B 所需的总成本是多少?

  • 首先,在 "任意次数交换 "步骤中,将 A=(A1,A2,,AN) 修改为 A=(AP1,AP2,,APN) 需要 inv(P) 次交换,其中 inv(P)P转换数。这需要 inv(P)Y 日元。

  • 接下来,在 "递增/递减任意次数 "步骤中,要使 A=(AP1,AP2,,APN) 等于 B ,需要 i=1N|APiBi| 次递增/递减(其中 || 表示绝对值)。这需要 i=1N|APiBi|X 日元。

因此

cost(P)=i=1N|APiBi|X+inv(P)Y .

因此,这个问题可以归结为 "通过选择合适的 P 来最小化 cost(P) 的优化问题"。

这里是

cost(P)

=i=1N|APiBi|X+inv(P)Y

=i=1N|APiBi|X+(i=1N#{j:j>i,Pj<Pi})Y

=i=1N(|APiBi|X+#{j:j>i,Pj<Pi}Y)

=i=1N(|APiBi|X+#{p:pN{P1,P2,,Pi1},p<Pi}Y)

其中 # 表示元素个数, N:={1,2,,N} 表示元素个数。

这里要注意, #{p:pN{P1,P2,,Pi1},p<Pi} 只取决于 {P1,P2,,Pi1}Pi ((而不是实际的排列 P1,P2,,Pi1)。
因此,对于 SNxNS 来说,定义

f(S,x):=#{p:pNS,p<x},

cost(P)=i=1N(|APiBi|X+f({P1,P2,,Pi1},Pi)Y).

因此,原来的问题可以改写如下。

你将按照 P1,P2,,PN 的顺序确定 P 的元素。当第一个 (i1) 元素 P1,P2,,Pi1 已经确定时,选择 x 作为下一个元素 Pi 的代价是

|AxBi|X+f({P1,P2,,Pi1},x)Y.

求确定 P 中所有元素的最小总成本。

我们将用动态程序设计法(DP)来解决这个问题。

P 的第一个 i 元素,即 P1,P2,,PiS={P1,P2,,Pi} 已经确定,那么我们就称这个状态为 S

当没有确定 P 中的元素时,状态为 。每当 P 中的一个元素被确定,当前状态就会发生变化,当 P 中的所有元素都被确定后,当前状态就会达到 N

对于 SN ,定义 dp[S] 如下。

dp[S]:= (到达状态 S 所需的最小总成本)

原问题的答案是达到状态 N 所需的最小总成本,即 dp[N]

首先,考虑 DP 的初始化。根据 dp[] 的定义、

dp[]=0 .

另外,为了方便起见,我们将 S 初始化为

dp[S] .

接下来,考虑 DP 的转换。

当当前状态为状态 S 时,我们可以选择 NS 中的任意元素 P#S+1 作为下一个元素。选择 P#S+1=xNS 需要花费 |AxB#S+1|X+f(S,x)Y 的代价,从而使当前状态变为状态 S{x}

相应地,对于每个 xNS ,我们有如下的转换:

dp[S{x}]min(dp[S{x}],dp[S]+|AxB#S+1|X+f(S,x)Y)

通过上述初始化和转换计算出 dp[] 后,该问题的答案为 dp[N]

因此,解决这个问题总共需要 O(N22N) 时间(或 O(N2N) 时间,取决于实现方式)。

C++ 代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll mod = 1e9 + 7;
const int N = 200005;
const ll INF = 1e18;
ll n, X, Y;
ll a[N], b[N], f[1 << 18];
int check(int s, int x) {
int res = 0;
for (int p = 1; p <= n; p++) {
if ((s & (1 << (p - 1))) == 0 && p < x) res++;
}
return res;
}
int main() {
scanf("%lld%lld%lld", &n, &X, &Y);
for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
for (int i = 1; i <= n; i++) scanf("%lld", &b[i]);
for (int i = 1; i < (1 << n); i++) {
f[i] = INF;
}
for (int s = 0; s < (1 << n); s++) {
int cnt = 0;
for (int i = 1; i <= n; i++)
if (s & (1 << (i - 1))) cnt++;
for (int x = 1; x <= n; x++) {
if (s & (1 << (x - 1))) continue;
f[s | (1 << (x - 1))] = min(f[s | (1 << (x - 1))], f[s] + abs(a[x] - b[cnt + 1]) * X + check(s, x) * Y);
}
}
printf("%lld\n", f[(1 << n) - 1]);
return 0;
}

本文作者:jxy2012的博客

本文链接:https://www.cnblogs.com/jxy2012/p/18132457

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   jxy2012  阅读(18)  评论(0编辑  收藏  举报
//雪花飘落效果
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起