题意: 大概就是两种颜色的数,数字是1 - n
的,总共2n
个数,然后每次可以交换相邻两个数字,最后让两种颜色的数字都是从小到大排序的。
举个例子
RBBRBR
颜色
231123
最终要结果是
RRBBBR
121233
也就是把R1
移到了最前的位置,B3
移到了B2
后面。这样总共交换了 5次,所以结果是 5。
题解: dp[i][j]
表示状态为前 i + j
已经放了i
个红色,j
个黑色,那么后面一个要么把 i + 1
的红色移到后面,要么是 把j + 1
的黑色移到后面。所以只要知道这两种状态的移到后面来需要的步数就可以了。这个步数就是 原本的位置 - 在他前面已经排好了的数字个数
,在他前面排好的数字个数又有两种颜色,不过没影响直接预处理就行了。
{
d
p
[
i
+
1
]
[
j
]
=
m
i
n
(
d
p
[
i
+
1
]
[
j
]
,
d
p
[
i
]
[
j
]
+
p
o
s
−
m
i
r
[
p
o
s
]
[
i
+
1
]
−
m
i
b
[
p
o
s
]
[
j
]
)
;
d
p
[
i
]
[
j
+
1
]
=
m
i
n
(
d
p
[
i
]
[
j
+
1
]
,
d
p
[
i
]
[
j
]
+
p
o
s
−
m
i
b
[
p
o
s
]
[
j
+
1
]
−
m
i
r
[
p
o
s
]
[
i
]
)
;
\begin{cases} dp[i + 1][j] = min(dp[i + 1][j], dp[i][j] + pos - mir[pos][i + 1] - mib[pos][j]);\\ dp[i][j + 1] = min(dp[i][j + 1], dp[i][j] + pos - mib[pos][j + 1] - mir[pos][i]); \end{cases}
{dp[i+1][j]=min(dp[i+1][j],dp[i][j]+pos−mir[pos][i+1]−mib[pos][j]);dp[i][j+1]=min(dp[i][j+1],dp[i][j]+pos−mib[pos][j+1]−mir[pos][i]);
mir[pos][i]
pos
位置 左边小于 i
的红色棋子个数
mir[pos][j]
pos
位置 左边小于 j
的黑色棋子个数
#include "bits/stdc++.h"
using namespace std;
int n;
int mir[6005][3005], mib[6005][3005];
int dp[3005][3005];
unordered_map<int, int> mpr, mpb;
int main() {
while (cin >> n) {
string s;
cin >> s;
vector<int> v;
for (int i = 0; i < 2 * n; i++) {
int x;
cin >> x;
if (s[i] == 'R') {
mpr[x] = i; //红色数字的位置
} else {
mpb[x] = i; //黑色数字的位置
}
v.emplace_back(x);
}
memset(mir, 0, sizeof(mir));
for (int i = 0; i < 2 * n; i++) { //预处理
if (i == 0)continue;
if (s[i - 1] == 'R') {
for (int j = 1; j <= n; j++) {
mib[i][j] = mib[i - 1][j];
}
for (int j = 1; j <= n; j++) {
if (j >= v[i - 1]) {
mir[i][j] = mir[i - 1][j] + 1;
} else {
mir[i][j] = mir[i - 1][j];
}
}
} else {
for (int j = 1; j <= n; j++) {
mir[i][j] = mir[i - 1][j];
}
for (int j = 1; j <= n; j++) {
if (j >= v[i - 1]) {
mib[i][j] = mib[i - 1][j] + 1;
} else {
mib[i][j] = mib[i - 1][j];
}
}
}
}
memset(dp, 1, sizeof(dp));
dp[0][0] = 0;
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= n; j++) {
int pos = mpr[i + 1];
if (i + 1 <= n) {
dp[i + 1][j] = min(dp[i + 1][j], dp[i][j] + pos - mir[pos][i + 1] - mib[pos][j]);
}
if (j + 1 <= n) {
pos = mpb[j + 1];
dp[i][j + 1] = min(dp[i][j + 1], dp[i][j] + pos - mib[pos][j + 1] - mir[pos][i]);
}
}
}
printf("%d\n", dp[n][n]);
}
return 0;
}