A
7的所有的余数都可以用1,6,8,9排列得到,然后搞一下就可以了。
B
可以用类似于单调队列的东西搞。具体看代码:
/* * Problem: B. Maximum Submatrix 2 * Author: Shun Yao * Note: 题目要求交换行,我写的交换列。于是把矩阵转换一下就可以。 */ #include <string.h> #include <stdlib.h> #include <limits.h> #include <assert.h> #include <stdio.h> #include <ctype.h> #include <math.h> #include <time.h> #include <map> #include <set> #include <list> #include <stack> #include <queue> #include <deque> #include <string> #include <vector> #include <bitset> #include <utility> #include <iomanip> #include <numeric> #include <sstream> #include <iostream> #include <algorithm> #include <functional> //using namespace std; const int MAXN = 5010, MAXM = 5010; int n, m, a[MAXN][MAXM], f[MAXN][MAXM]; char s[MAXN][MAXM]; int main(/*int argc, char **argv*/) { int i, j, k, l, ans; // freopen("B.in", "r", stdin); // freopen("B.out", "w", stdout); scanf("%d%d", &n, &m); for (i = 1; i <= n; ++i) scanf(" %s", s[i] + 1); ans = 0; for (i = 1; i <= n; ++i) { a[0][i] = i; f[0][i] = 0; } for (i = 1; i <= m; ++i) { l = 0; for (j = 1; j <= n; ++j) { k = a[i - 1][j]; if (s[k][i] == '1') { f[i][k] = f[i - 1][k] + 1; a[i][++l] = k; ans = std::max(ans, f[i][k] * l); } else f[i][k] = 0; } for (j = 1; j <= n; ++j) if (f[i][j] == 0) a[i][++l] = j; } printf("%d", ans); fclose(stdin); fclose(stdout); return 0; }
C
题目中实际上有提示,用dp[i][j][k]表示在(i, j),过所有object的射线的奇偶性为k的最小步数。
/* * Problem: C. Circling Round Treasures * Author: Shun Yao */ #include <string.h> #include <stdlib.h> #include <limits.h> #include <assert.h> #include <stdio.h> #include <ctype.h> #include <math.h> #include <time.h> #include <map> #include <set> #include <list> #include <stack> #include <queue> #include <deque> #include <string> #include <vector> #include <bitset> #include <utility> #include <iomanip> #include <numeric> #include <sstream> #include <iostream> #include <algorithm> #include <functional> //using namespace std; const int MAXN = 22, MAXM = 22, dx[4] = {0, 0, 1, -1}, dy[4] = {1, -1, 0, 0}; int n, m, a[MAXN][MAXM], sum[333], f[MAXN][MAXM][333]; char s[MAXN][MAXM]; class Data { public: int x, y, k; Data(int X, int Y, int K) : x(X), y(Y), k(K) {} } ; std::queue<Data> q; int main(/*int argc, char **argv*/) { int bomb, object, tl, i, j, k, x, y, trea[10], treasure[10], sx, sy, xx, yy, kk, ans; scanf("%d%d", &n, &m); for (i = 1; i <= n; ++i) scanf(" %s", s[i] + 1); bomb = 0; object = 0; tl = 0; for (i = 1; i <= n; ++i) for (j = 1; j <= m; ++j) { switch (s[i][j]) { case 'B': ++object; bomb += 1 << (object - 1); for (k = 1; k <= i; ++k) a[k][j] += 1 << (object - 1); break; case 'S': s[i][j] = '.'; sx = i; sy = j; break; case '.': break; case '#': break; default: ++tl; ++object; trea[s[i][j] - '0'] = 1 << (object - 1); for (k = 1; k <= i; ++k) a[k][j] += 1 << (object - 1); } } for (i = 1; i <= tl; ++i) scanf("%d", &treasure[i]); for (i = 0; i < 1 << object; ++i) if ((i & bomb) == 0) for (j = 1; j <= tl; ++j) if (i & trea[j]) sum[i] += treasure[j]; //bfs----------------------------------------------------------------------- memset(f, -1, sizeof f); f[sx][sy][0] = 0; q.push(Data(sx, sy, 0)); ans = 0; while (!q.empty()) { x = q.front().x; y = q.front().y; k = q.front().k; q.pop(); if (x == sx && y == sy) ans = std::max(ans, sum[k] - f[x][y][k]); for (i = 0; i < 4; ++i) { xx = x + dx[i]; yy = y + dy[i]; if (xx < 1 || xx > n || yy < 1 || yy > m || s[xx][yy] != '.') continue; kk = k; if (i == 0) kk ^= a[xx][yy]; if (i == 1) kk ^= a[x][y]; if (f[xx][yy][kk] == -1) { f[xx][yy][kk] = f[x][y][k] + 1; q.push(Data(xx, yy, kk)); } } } printf("%d", ans); fclose(stdin); fclose(stdout); return 0; }
D
启发式合并平衡树 或者 莫队算法(其实dfs后分块做也可以)。
E
官方给的是线性规划。dp也可以过。