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_;
}
};
操作一:打印出圆环的第一个字符
操作二:把圆环顺时针或逆时针转一个位置
问打印此字符串最少需要多少步操作?
思路:用动归解决。将字符串拆分为单个字符,每一轮只考虑当前要打印的字符(假设为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_;
}
};
相关文章推荐
- 629. K Inverse Pairs【Hard】 动态规划
- AtCoder Regular Contest 066 E - Addition and Subtraction Hard 动态规划
- 87. Scramble String *HARD* 动态规划
- 312. Burst Balloons 难度:hard 类别:分治、动态规划
- 689. Maximum Sum of 3 Non-Overlapping Subarrays 【Hard】 动态规划
- 115.leetcode Distinct Subsequences(hard)[动态规划]
- 动态规划套路在最长公共子串、最长公共子序列和01背包问题中的应用
- 算法导论:钢条切割(java动态规划实现)
- 【算法导论实验4】动态规划-最长公共子序列LCS
- Hard-题目44:30. Substring with Concatenation of All Words
- P NP NPC NP-hard问题的区别
- Climbing Stairs:动态规划
- 动态规划——最长公共子串
- [置顶] 0-1背包 动态规划
- CodeForces 615B Longtail Hedgehog(长尾巴的刺猬) 动态规划
- POJ-1157 LITTLE SHOP OF FLOWERS(动态规划)
- 动态规划求解0-1背包
- 最长公共子序列&&最长公共子串---[动态规划]
- P,NP,NPC,NP-hard
- C - A very hard mathematic problem