总分:250
T1:AC
T2:AC
正解思路:纯模拟
- 构建地图,找马
- 循环八个方向并判断别马腿情况,以及是否有小写字母
- tips:两个方向为一组开方向数组,可以统一考虑别马腿
T3:30
开一个数组t,有三种情况:
- a[i] > a[i - 1]:我们记为
- a[i] < a[i - 1]:我们记为
- a[i] = a[i - 1]:我们记为
这里波动值就是m,而 就是m使用的前缀和
此时又有2种情况:
- :这种情况m取任何值都可以
- :这种情况m就是
注:一定要判断能否整除以及m>=0
详细见代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| #include<iostream> #include<map> #include<cmath> #include<algorithm> #define int long long using namespace std;
const int N = 1e6 + 5;
int a[N], op[N]; map<int, int> mapp; int n, cnt = 0, maxx = 0;
signed main() { cin >> n; for (int i = 1; i <= n; ++i) cin >> a[i]; for (int i = 1; i <= n; ++i) if (i != 1) { if (a[i] == a[i - 1]) op[i] = 0; if (a[i] < a[i - 1]) op[i] = -1; if (a[i] > a[i - 1]) op[i] = 1; } int bd, t = 0; for (int i = 2; i <= n; ++i) { int now = a[i], start = a[1]; cnt += op[i]; if (cnt == 0) { if (now == start) t++; continue; } if ((now - start) % cnt == 0){ int m = now - start / cnt; if (m > 0) mapp[m]++; } } for (auto it = mapp.begin(); it != mapp.end(); ++it) if (maxx <= it->second) { maxx = it->second; bd = it->first; } cout << maxx + t + 1 << "\n" << bd << "\n"; return 0; }
|
T4:20 (输出impossible骗20,老师太善良了)
40分思路:
先判断impossible可能性,然后剩下用bfs暴搜。
用一个map或set去重,但我们不需要排序功能,所以用unordered方案。
记录每一种有变化的序列,即如果swap之后序列改变了,就是一种新的方案,再去判断可不可行。
100分思路:
一个四维dp
整体思路是把整个序列清空,再放回去重新排列。
状态: 其中 a、c、k 是已经放回去的a、c、k的个数,last是上一个放下的字母
我们先定义一个变量cost,表示把这个字母放到新序列的花费(即它要移动的步数)。
假设现在要放A, ,这里的pos数组表示的是这个字母(此处是A)在原序列的位置,后面要减去c和k是因为要排除掉没被移动的部分,与0去max是为了避免负花费。
假设现在要放A的状态转移方程: 。这里面a要减1是因为要知道还没放下A时的花费,上一个有可能放的C,有可能放的K,去其中最小值最后+把A放在新序列里的花费,也就是cost。
最后答案是 与 与 的最小值,其中na、nc、nk指的是A、C、K的数量。取它们仨的最小值是去选第一张为A、C、K三种情况花费(移动步数)最小的那一种方案,输出。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| ```cpp #include <iostream> #include <string> #include <vector> #include <algorithm>
using namespace std;
const int INF = 1e9;
int main() { string s; cin >> s; int n = s.length(); vector<int> posA, posC, posK; vector<int> A(n, 0), C(n, 0), K(n, 0);
for (int i = 0; i < n; i++) { A[i] = A[i - 1] + (s[i] == 'A'); C[i] = C[i - 1] + (s[i] == 'C'); K[i] = K[i - 1] + (s[i] == 'K'); if (s[i] == 'A') posA.push_back(i); else if (s[i] == 'C') posC.push_back(i); else posK.push_back(i); }
int na = posA.size(); int nc = posC.size(); int nk = posK.size();
int max_allowed = (n + 1) / 2; if (na > (n + 1) / 2 || nc > (n + 1) / 2 || nk > (n + 1) / 2) { cout << "Impossible!\n"; return 0; }
vector<vector<vector<vector<int>>>> dp(na + 1, vector<vector<vector<int >>> (nc + 1, vector<vector<int >> (nk + 1, vector<int>(3, INF))));
dp[0][0][0][0] = 0; dp[0][0][0][1] = 0; dp[0][0][0][2] = 0;
for (int a = 0; a <= na; a++) for (int c = 0; c <= nc; c++) for (int k = 0; k <= nk; k++) { if (a == 0 && c == 0 && k == 0) continue;
if (a > 0) { int cost = max(0, C[posA[a - 1]] - c) + max(0, K[posA[a - 1]] - k); dp[a][c][k][0] = min(dp[a - 1][c][k][1], dp[a - 1][c][k][2]) + cost; }
if (c > 0) { int cost = max(0, A[posC[c - 1]] - a) + max(0, K[posC[c - 1]] - k); dp[a][c][k][1] = min(dp[a][c - 1][k][0], dp[a][c - 1][k][2]) + cost; }
if (k > 0) { int cost = max(0, A[posK[k - 1]] - a) + max(0, C[posK[k - 1]] - c); dp[a][c][k][2] = min(dp[a][c][k - 1][0], dp[a][c][k - 1][1]) + cost; } } int ans = min({dp[na][nc][nk][0], dp[na][nc][nk][1], dp[na][nc][nk][2]}); if (ans >= INF) cout << "Impossible!\n"; else cout << ans << "\n";
return 0; }
|