标签:cal cond print 国际 min ... line assert fprintf
http://codeforces.com/contest/1065/problem/D
我个傻 x 以为对角线移动就是 \((x,y) \rightarrow (x+d,y+d)\)。。。
\(N\) 行 \(N\) 列的国际象棋的棋盘上有一些数字,你要从 \(1\) 的位置开始,先移动到 \(2\) 的位置,然后移动到 \(3\) ,……,最后移动到 \(N^{2}\)。你只能使用主教、车、骑士三种,每一步你可以进行两种操作之一:
求最小的移动步数。若有多个移动步数最小的方案,输出换棋子操作数量最少的那个。
大力建图跑最短路即可。
#include <bits/stdc++.h>
#ifdef LOCAL
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define debug(...) 0
#endif
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int, int> pii;
int rint() {
int n, c, sgn = 0;
while ((c = getchar()) < ‘-‘);
if (c == ‘-‘) n = 0, sgn = 1;
else n = c - ‘0‘;
while ((c = getchar()) >= ‘0‘) {
n = 10 * n + c - ‘0‘;
}
return sgn ? -n : n;
}
const int N = 123;
const int INF = 1e9;
const bool DEBUG = false;
int n;
pii p[N];
vector<pii> mv[3];
pii dist[3][15][15];
pii cost[N][3][3];
pii dp[N][3];
pair<int, int> operator + (const pii &A, const pii &B) {
return {A.first + B.first, A.second + B.second};
}
int main() {
scanf("%d", &n);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
int num;
scanf("%d", &num);
p[num] = {i, j};
assert(1 <= num && num <= n * n);
}
}
for (int x : {-1, 1}) {
for (int y : {-2, 2}) {
mv[0].emplace_back(x, y);
mv[0].emplace_back(y, x);
}
}
for (int i = 1; i < n; i++) {
if (i == 0) continue;
mv[1].emplace_back(i, i);
mv[1].emplace_back(-i, -i);
mv[1].emplace_back(i, -i);
mv[1].emplace_back(-i, i);
}
for (int i = -n + 1; i < n; i++) {
if (i == 0) continue;
mv[2].emplace_back(i, 0);
mv[2].emplace_back(0, i);
}
for (int st = 1; st < n * n; st++) {
for (int ts = 0; ts < 3; ts++) {
set< pair< pii, pair<int, pii> > > que;
int xs, ys;
tie(xs, ys) = p[st];
for (int i = 0; i < 3; i++) {
for (int x = 0; x < n; x++) {
for (int y = 0; y < n; y++) {
dist[i][x][y] = {INF, INF};
}
}
}
que.insert(make_pair(make_pair(0, 0), make_pair(ts, make_pair(xs, ys))));
dist[ts][xs][ys] = pii(0, 0);
while (!que.empty()) {
auto p = *(que.begin());
que.erase(que.begin());
int x, y;
tie(x, y) = p.second.second;
int t = p.second.first;
auto d = p.first;
for (int t2 = 0; t2 < 3; t2++) if (t != t2) {
if (d + pii(1, 1) >= dist[t2][x][y]) continue;
que.erase(make_pair(dist[t2][x][y], make_pair(t2, make_pair(x, y))));
dist[t2][x][y] = d + pii(1, 1);
que.insert(make_pair(dist[t2][x][y], make_pair(t2, make_pair(x, y))));
}
for (auto &p : mv[t]) {
int x2 = x + p.first;
int y2 = y + p.second;
assert((x != x2) + (y != y2) >= 1);
if (x2 < 0 || x2 >= n || y2 < 0 || y2 >= n) continue;
if (d + pii(1, 0) >= dist[t][x2][y2]) continue;
que.erase(make_pair(dist[t][x2][y2], make_pair(t, make_pair(x2, y2))));
dist[t][x2][y2] = d + pii(1, 0);
que.insert(make_pair(dist[t][x2][y2], make_pair(t, make_pair(x2, y2))));
}
}
for (int tf = 0; tf < 3; tf++) {
int xf, yf;
tie(xf, yf) = p[st + 1];
cost[st][ts][tf] = dist[tf][xf][yf];
}
}
}
for (int i = 0; i < 3; i++) {
dp[1][i] = pii(0, 0);
}
for (int i = 1; i < n * n; i++) {
for (int b = 0; b < 3; b++) {
dp[i + 1][b] = {INF, INF};
}
for (int a = 0; a < 3; a++) {
for (int b = 0; b < 3; b++) {
dp[i + 1][b] = min(dp[i + 1][b], dp[i][a] + cost[i][a][b]);
}
}
}
auto ans = *min_element(dp[n * n], dp[n * n] + 3);
printf("%d %d\n", ans.first, ans.second);
return 0;
}
Educational Codeforces Round #52 D. Three Pieces
标签:cal cond print 国际 min ... line assert fprintf
原文地址:https://www.cnblogs.com/hfccccccccccccc/p/9777426.html