11.12
t1
\(O(nm^2)\)是简单的。
发挥人类智慧发现每次最优只在前面较少的状态。
于是可过。
其实人类智慧有证明的。
考虑若最大值越大,则选的次数越小,反之亦然。
平均一下就过了。
code
t1
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
const int M = 5e3 + 10;
int n, m;
int a[N], b[N], pos[M];
int dp[N][M];signed main()
{freopen("crazy.in", "r", stdin);freopen("crazy.out", "w", stdout);ios::sync_with_stdio(0);cin.tie(0);cin >> n >> m;for (int i = 1; i <= n; ++i)cin >> a[i], b[i] = a[i];sort(b + 1, b + 1 + n);for (int i = 0; i <= m; ++i)pos[i] = upper_bound(b + 1, b + 1 + n, i) - b - 1;memset(dp, 0x3f, sizeof(dp));dp[0][0] = 0;for (int i = 1; i <= n; ++i){for (int j = 0; j <= m; ++j)for (int k = max(j - 100, 0); k <= j; ++k)dp[i][j] = min(dp[i][j], dp[i - 1][k] + n - pos[j - k]);}cout << dp[n][m];return 0;
}
t2
dp加一吨特判。
赛事困+左右脑互搏,写了个抽象东西dfs。
本质就是dp中的一种转移,我也不知道为啥写个dfs转移。
code
t2
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
int T, n, m;
int a[N][N], dp[N][N];int val(int x, int y, int c, int d)
{if (a[x][y] ^ a[c][d])return (a[c][d] && !a[x][y]);elsereturn 0;
}inline void solve()
{cin >> n >> m;for (int i = 1; i <= n; ++i)for (int j = 1; j <= m; ++j)cin >> a[i][j];if ((n == 1 && m == 1 && a[1][1]) || (n * m == 2 && (a[1][1] ^ a[n][m]))){cout << "Impossible\n";return;}if (n == 1){int tot = 0, lst = 0;for (int i = 1; i <= m; ++i){if (a[1][i])lst = i, ++tot;dp[1][i] = dp[1][i - 1] + val(1, i - 1, 1, i);}if (tot == 1)dp[n][m] = 2 + ((lst - 1) <= 1 && (m - lst) <= 1);cout << dp[n][m] << "\n";return;}if (m == 1){int tot = 0, lst = 0;for (int i = 1; i <= n; ++i){if (a[i][1])lst = i, ++tot;dp[i][1] = dp[i - 1][1] + val(i - 1, 1, i, 1);}if (tot == 1)dp[n][m] = 2 + ((lst - 1) <= 1 && (n - lst) <= 1);cout << dp[n][m] << "\n";return;}for (int i = 1; i <= n; ++i){for (int j = 1; j <= m; ++j){if (i == 1 && j == 1)dp[i][j] = a[i][j];else if (i == 1)dp[i][j] = dp[i][j - 1] + val(i, j - 1, i, j);else if (j == 1)dp[i][j] = dp[i - 1][j] + val(i - 1, j, i, j);elsedp[i][j] = min(dp[i][j - 1] + val(i, j - 1, i, j), dp[i - 1][j] + val(i - 1, j, i, j));}}cout << dp[n][m] << "\n";
}signed main()
{freopen("flip.in", "r", stdin);freopen("flip.out", "w", stdout);ios::sync_with_stdio(0);cin.tie(0);cin >> T;while (T--)solve();return 0;
}
t3
你直接出那个ds都是吉司机线段树。
然后还变成神秘东西???
神人题,神人做。
t4
如果发现了是最短路就可以秒。
相邻两个非冰的块次数为2。
每次向上下左右扩展到的第一个冰的之前的块次数为1(单向边)。
然后dij即可。
code
t4
#include <bits/stdc++.h>
#define pir pair<int, int>
#define fi first
#define se second
using namespace std;
const int N = 1e3 + 10;
int n, m, x1, y3, x2, y2;
vector<pir> e[N * N];
char c[N][N];
int dis[N * N];
bool flag[N * N];
priority_queue<pir, vector<pir>, greater<pir>> q;inline int get_id(int i, int j) { return (i - 1) * m + j; }inline void dij(int op)
{memset(dis, 0x3f, sizeof(dis));memset(flag, 0, sizeof(flag));dis[op] = 0;q.push(make_pair(0, op));while (q.size()){int x = q.top().se;q.pop();if (flag[x])continue;flag[x] = 1;for (auto y : e[x]){if (dis[y.fi] > dis[x] + y.se){dis[y.fi] = dis[x] + y.se;q.push(make_pair(dis[y.fi], y.fi));}}}
}signed main()
{freopen("skate.in", "r", stdin);freopen("skate.out", "w", stdout);ios::sync_with_stdio(0);cin.tie(0);cin >> n >> m;for (int i = 1; i <= n; ++i)for (int j = 1; j <= m; ++j)cin >> c[i][j];for (int i = 1; i <= n; ++i)for (int j = 1; j <= m; ++j){if (c[i][j] == '#')continue;if (c[i - 1][j] == '.')e[get_id(i, j)].emplace_back(make_pair(get_id(i - 1, j), 2));if (c[i][j - 1] == '.')e[get_id(i, j)].emplace_back(make_pair(get_id(i, j - 1), 2));if (c[i + 1][j] == '.')e[get_id(i, j)].emplace_back(make_pair(get_id(i + 1, j), 2));if (c[i][j + 1] == '.')e[get_id(i, j)].emplace_back(make_pair(get_id(i, j + 1), 2));int nx = i, ny = j;while (c[nx][ny] == '.') // up--nx;++nx;if (!(nx == i && ny == j))e[get_id(i, j)].emplace_back(make_pair(get_id(nx, ny), 1));nx = i, ny = j;while (c[nx][ny] == '.') // left--ny;++ny;if (!(nx == i && ny == j))e[get_id(i, j)].emplace_back(make_pair(get_id(nx, ny), 1));// cout << "nx=" << nx << " ny=" << ny << "\n";nx = i, ny = j;while (c[nx][ny] == '.') // down++nx;--nx;if (!(nx == i && ny == j))e[get_id(i, j)].emplace_back(make_pair(get_id(nx, ny), 1));// cout << "nx=" << nx << " ny=" << ny << "\n";nx = i, ny = j;while (c[nx][ny] == '.') // right++ny;--ny;if (!(nx == i && ny == j))e[get_id(i, j)].emplace_back(make_pair(get_id(nx, ny), 1));}cin >> x1 >> y3 >> x2 >> y2;dij(get_id(x1, y3));cout << (dis[get_id(x2, y2)] > 100000000 ? -1 : dis[get_id(x2, y2)]);return 0;
}
紧急写的(10min),仓促。