A 保龄球游戏的获胜者
模拟
class Solution {
public:
int isWinner(vector<int> &a1, vector<int> &a2) {
int n = a1.size();
int s1 = a1[0], s2 = a2[0];
if (n != 1) {
s1 += a1[0] == 10 ? 2 * a1[1] : a1[1];
s2 += a2[0] == 10 ? 2 * a2[1] : a2[1];
}
for (int i = 2; i < n; i++) {
s1 += max(a1[i - 2], a1[i - 1]) == 10 ? 2 * a1[i] : a1[i];
s2 += max(a2[i - 2], a2[i - 1]) == 10 ? 2 * a2[i] : a2[i];
}
if (s1 > s2)
return 1;
else if (s1 < s2)
return 2;
return 0;
}
};
B 找出叠涂元素
模拟:记录各行各列已有元素数
class Solution {
public:
int firstCompleteIndex(vector<int> &a, vector<vector<int>> &g) {
int len = a.size(), m = g.size(), n = g[0].size();
vector<pair<int, int>> li(len);
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++) {
li[g[i][j] - 1] = {i, j};
}
vector<int> cnt_row(m), cnt_col(n);
int res;
for (int i = 0; i < len; i++) {
if (++cnt_row[li[a[i] - 1].first] == n) {
res = i;
break;
}
if (++cnt_col[li[a[i] - 1].second] == m) {
res = i;
break;
}
}
return res;
}
};
C 前往目标的最小代价
dijkstra:先建图用n*2+2个点存储所有边的端点、起点和终点,然后建边,之后从起点跑dijkstra
class Solution {
public:
inline int get_dis(pair<int, int> &a, pair<int, int> &b) {
return abs(a.first - b.first) + abs(a.second - b.second);
}
int minimumCost(vector<int> &start, vector<int> &target, vector<vector<int>> &e) {
int n = e.size();
int m = n * 2 + 2;
vector<pair<int, int>> a(m);
vector<pair<int, int>> edge[m];
for (int i = 0; i < n; i++) {
a[i * 2] = {e[i][0], e[i][1]};
a[i * 2 + 1] = {e[i][2], e[i][3]};
}
a[n * 2] = {start[0], start[1]};//起点
a[n * 2 + 1] = {target[0], target[1]};//终点
for (int i = 0; i < n; i++) {
edge[i * 2].emplace_back(i * 2 + 1, e[i][4]);
for (int j = 0; j < m; j++) {//建边
if (j != i * 2)
edge[i * 2].emplace_back(j, get_dis(a[j], a[i * 2]));
if (j != i * 2 + 1)
edge[i * 2 + 1].emplace_back(j, get_dis(a[j], a[i * 2 + 1]));
}
}
for (int j = 0; j < m; j++)//建边
if (j != n * 2)
edge[n * 2].emplace_back(j, get_dis(a[j], a[n * 2]));
vector<int> vis(m);
long long inf = 1e10;
vector<long long> d(m, inf);
d[n * 2] = 0;
int tar = n * 2 + 1;
while (1) {
long long mn = inf, cur;
for (int i = 0; i < m; i++) {
if (!vis[i] && d[i] < mn) {
mn = d[i];
cur = i;
}
}
vis[cur] = 1;
if (cur == tar)
break;
for (auto [j, c]: edge[cur]) {
if (!vis[j] && d[cur] + c < d[j])
d[j] = d[cur] + c;
}
}
return d[tar];
}
};
D 字典序最小的美丽字符串
脑筋急转弯:任意s[i]若s[i]!=s[i-1]&&s[i]!=s[i-2],则s满足不包含任何长度>1的回文子字符串,所以可以对s从后往前枚举每一位,判断当前位是否可以满足条件地变大,找到这样的位置将其变大,并将其右边最小化(同时用s[i]!=s[i-1]&&s[i]!=s[i-2]保证不存在长>1的回文串),因为题目k>=4,所以将其右边最小化采用按位枚举一定有解
class Solution {
public:
string smallestBeautifulString(string s, int k) {
int n = s.size();
int i = n - 1;
int j;
while (i >= 0) {//找到最右边可以满足条件地变大的位置
int can = 0;
for (j = s[i] + 1; j - 'a' < k; j++) {
if ((i - 1 < 0 || j != s[i - 1]) && (i - 2 < 0 || j != s[i - 2])) {
can = 1;
break;
}
}
if (can)
break;
i--;
}
if (i == -1)
return "";
s[i] = j;
for (i = i + 1; i < n; i++) {//右边最小化
for (j = 'a'; j - 'a' < k; j++) {
if ((i - 1 < 0 || j != s[i - 1]) && (i - 2 < 0 || j != s[i - 2])) {
s[i] = j;
break;
}
}
}
return s;
}
};