您的位置:首页 > 大数据 > 人工智能

514. Freedom Trail 【Hard】 动态规划

2017-11-01 14:26 148 查看
问题:给定一个圆环(初始字符为第一个)和一个字符串,进行如下操作直至打印出此字符串——

操作一:打印出圆环的第一个字符

操作二:把圆环顺时针或逆时针转一个位置

问打印此字符串最少需要多少步操作?

思路:用动归解决。将字符串拆分为单个字符,每一轮只考虑当前要打印的字符(假设为X)——对圆环上的每个X,求出其从上一轮到这一轮的最小距离dist(X)。

距离指圆环上的顺时针or逆时针最短距离。

如果是第一轮,那么每个X的dist(X)为它的位置到0的距离再加一(加一是因为要打印)

如果是第N轮(N>1),假设上一轮要打印的字符为S(则每个S都在上一轮都已经有一个dist值了),那么每个X的dist(X)为:它的位置到圆环上各个S的距离分别加上dist(S)的最小值,再加一(加一是因为要打印)

最终动归出最后一个字符Z,在dist(Z)中找到最小值打印出来就可以了。

难度还可以,主要是明确了思路就好了,时间都花在了debug上面。

vector<int> max_vector_initializer(100, 9999999);

int min_num(int x, int y) {
if (x > y) return y;
else return x;
}

int abs(int d) {
if (d > 0) return d;
else return -d;
}

int C2I(char c) {
return (int)(c - 'a');
}

int dist(int p1, int p2, int lr) {
int abs_dis = abs(p1 - p2);
return min_num(abs_dis, lr - abs_dis);
}

class Solution {
public:
int findRotateSteps(string ring, string key) {

vector<int> mapping[26];
int lr = ring.size();
int lk = key.size();
int pos;
for (int i = 0; i < lr; ++i) {
pos = C2I(ring[i]);
mapping[pos].push_back(i);
}

vector<int> a(100, 9999999);
vector<int> b(100, 9999999);
for (int it = 0; it < lk; ++it) {
b = a; // b is the previous state
a = max_vector_initializer; // initialize a to a max vector

int prev, next, d;
int prev_c = (it == 0 ? -1 : C2I(key[it - 1]));
int next_c = C2I(key[it]);
if (prev_c == -1) {
for (int j = 0; j < mapping[next_c].size(); ++j) {
next = mapping[next_c][j];
a[next] = dist(0, next, lr) + 1;
}
} else {
for (int i = 0; i < mapping[prev_c].size(); ++i) {
for (int j = 0; j < mapping[next_c].size(); ++j) {
prev = mapping[prev_c][i];
next = mapping[next_c][j];
d = dist(prev, next, lr);
a[next] = min_num(a[next], b[prev] + 1 + d);
}
}
}
}

int pos_c = C2I(key[lk - 1]);
int _min_ = 9999999;
for (int i = 0; i < mapping[pos_c].size(); ++i) {
pos = mapping[pos_c][i];
if (_min_ > a[pos]) {
_min_ = a[pos];
}
}
return _min_;

}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: