看到一道美团(不知道什么时候)的笔试题,问题描述如下:
在网上查到过其他网友的解法,感觉和我的理解不太一样, 这里写一下我自己对题目的理解。
我比较疑惑的是小美跳方格的方式,是每次移动一格,还是可跳到任意位置。如果是前者的话,那么就只存在两种情况:一是不存在数值连续的路径,那么无解;二是有解,最优路径一定为k-1。这么看的话显得题目很多条件都没用,也比较简单。那估计不是这么个事了。
我采取了另一种理解方式,小美可以跳到任意一格,每次移动都计算曼哈顿距离。假设当前位置的数字为i,那么下一位置的数字一定为i+1,则可以通过对所有格子分组的方式确定下一位置的可能解。然后通过递归的方法求解最优路径。
(按照这个思路写了代码,简单测试发现是可行的)
// 4.14 小美的跳方格
#include <cstdio>
#include <vector>
#include <stack>
#pragma warning(disable:4996)
int n;
int k;
std::vector<std::vector<std::pair<int, int>>> classes;
std::vector<int> fun(int layer) {
std::vector<int> costs;
if (layer + 1 >= k) {
for (int i = 0; i < classes[layer].size(); i++) {
costs.push_back(0);
}
return costs;
}
std::vector<int> costs_next = fun(layer + 1);
for (int i = 0; i < classes[layer].size(); i++) {
int cost = -1;
for (int j = 0; j < classes[layer + 1].size(); j++) {
int tmp_cost = costs_next[j];
if (tmp_cost == -1) continue;
tmp_cost = tmp_cost +
abs(classes[layer + 1][j].first - classes[layer][i].first) +
abs(classes[layer + 1][j].second - classes[layer][i].second);
if (cost == -1 || (cost != -1 && tmp_cost < cost)) {
cost = tmp_cost;
}
}
costs.push_back(cost);
}
return costs;
}
int main() {
// 输入数据
scanf("%d %d", &n, &k);
std::vector<std::vector<int>> data;
for (int i = 0; i < k; i++) {
std::vector<std::pair<int, int>> tmp;
classes.push_back(tmp);
}
for (int i = 0; i < n; i++) {
std::vector<int> data_tmp;
for (int j = 0; j < n; j++) {
int num;
scanf("%d", &num);
data_tmp.push_back(num);
data_tmp.push_back(0);
std::pair<int, int> pos = std::make_pair(i, j);
classes[num - 1].push_back(pos);
}
data.push_back(data_tmp);
}
int cost = -1;
std::vector<int> costs_next = fun(0);
for (int i = 0; i < costs_next.size(); i++) {
int tmp_cost = costs_next[i];
if (tmp_cost == -1) continue;
if (cost == -1 || (cost != -1 && tmp_cost < cost)) {
cost = tmp_cost;
}
}
printf("%d", cost);
return 0;
}