noip6 &&多校1
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]);
else
return 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);
else
dp[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),仓促。
本文来自博客园,作者:HS_fu3,转载请注明原文链接:https://www.cnblogs.com/HS-fu3/p/19215654

浙公网安备 33010602011771号