标签:
Problem A Calculus Midterm
题意:略
题解:~~
Problem B 翻翻棋
题意:略
题解:~~
Problem C 平行四边形数
题意:略
题解:~~
Problem D 炉石传说
题意:略
题解:最直接的一个做法就是二分图,跑一遍判断是否匹配的数量为n。还可以的一个做法是贪心:先把对手的血量从大到小排,然后对于自己,选一个能满足对方攻击的自身攻击力最小的一个随从,然后不断重复,最后判断有无可选即可。
1 /*zhen hao*/
2 #include <cstdio>
3 #include <cstring>
4 #include <iostream>
5 using namespace std;
6
7 #define lson l, m, rt << 1
8 #define rson m + 1, r, rt << 1 | 1
9 #define ll long long
10 #define xx first
11 #define yy second
12
13 const int maxn = 110;
14 int n, from[maxn], used[maxn];
15 int G[maxn][maxn], a[maxn], b[maxn], c[maxn], d[maxn];
16
17 bool is_match(int u) {
18 for (int v = 0; v < n; v++) if (G[u][v] && !used[v]) {
19 used[v] = 1;
20 if (from[v] == -1 || is_match(from[v])) {
21 from[v] = u;
22 return true;
23 }
24 }
25 return false;
26 }
27
28 int max_match() {
29 int ret = 0;
30 memset(from, -1, sizeof from);
31 for (int i = 0; i < n; i++) {
32 memset(used, 0, sizeof used);
33 ret += is_match(i);
34 }
35 return ret;
36 }
37
38 int main() {
39 // freopen("case.in", "r", stdin);
40 int T;
41 cin >> T;
42 while (T--) {
43 scanf("%d", &n);
44 for (int i = 0; i < n; i++) scanf("%d%d", a + i, b + i);
45 for (int i = 0; i < n; i++) scanf("%d%d", c + i, d + i);
46 memset(G, 0, sizeof G);
47 for (int i = 0; i < n; i++)
48 for (int j = 0; j < n; j++) {
49 if (a[i] - d[j] > 0 && c[j] - b[i] <= 0) G[i][j] = 1;
50 }
51 if (max_match() == n) puts("Yes"); else puts("No");
52 }
53 return 0;
54 }
1 /*zhen hao*/
2 #include <cstdio>
3 #include <vector>
4 #include <cstring>
5 #include <queue>
6 #include <algorithm>
7 using namespace std;
8
9 #define lson l, m, rt << 1
10 #define rson m + 1, r, rt << 1 | 1
11 #define xx first
12 #define yy second
13
14 typedef pair<int,int> pii;
15 typedef long long ll;
16 const int maxn = 110, inf = 1 << 20;
17 int n;
18
19 struct Node {
20 int x, y, isdeath;
21 Node(int x=0, int y=0, int isdeath=0) : x(x), y(y), isdeath(isdeath) {}
22 bool operator < (const Node& o) const {
23 return x > o.x;
24 }
25 };
26
27 Node a[maxn], b[maxn];
28
29 bool check() {
30 for (int i = 0; i < n; i++) {
31 int best = inf, bestid;
32 for (int j = 0; j < n; j++) if (!a[j].isdeath) {
33 if (a[j].x - b[i].y > 0 && b[i].x - a[j].y <= 0) {
34 if (best > a[j].x) best = a[bestid = j].x;
35 }
36 }
37 if (best == inf) return false;
38 a[bestid].isdeath = 1;
39 }
40 return true;
41 }
42
43 int main() {
44 // freopen("case.in", "r", stdin);
45 int T;
46 scanf("%d", &T);
47 while (T--) {
48 scanf("%d", &n);
49 for (int i = 0; i < n; i++) scanf("%d%d", &a[i].x, &a[i].y);
50 for (int i = 0; i < n; i++) scanf("%d%d", &b[i].x, &b[i].y);
51 for (int i = 0; i < n; i++) a[i].isdeath = b[i].isdeath = 0;
52 sort(b, b + n);
53 check() ? puts("Yes") : puts("No");
54 }
55 return 0;
56 }
Problem E ~APTX4869
题意:略
题解:对于这种最小值最大化的问题,用二分答案来处理。先二分出一个答案,然后对于每一对点如果小于这个答案那么一定要放在同一个集合,所以就连一条边代表这两个点一定是同一集合,然后最后dfs一个点,把能够标记的点都标记,最后看有没有剩下点,有的话就说明这个方案是合法的,否则不合法,然后不断往下分。
1 /*zhen hao*/
2 #include <vector>
3 #include <cstring>
4 #include <cstdio>
5 using namespace std;
6
7 #define lson l, m, rt << 1
8 #define rson m + 1, r, rt << 1 | 1
9 #define ll long long
10 #define xx first
11 #define yy second
12
13 const int maxn = 8e2 + 10;
14 int v[maxn][maxn], id[maxn], n;
15 vector<int> G[maxn];
16
17 void dfs(int u) {
18 id[u] = 1;
19 for (int i = 0; i < (int)G[u].size(); i++) {
20 int v = G[u][i];
21 if (id[v] == -1) dfs(v);
22 }
23 }
24
25 bool check(int M) {
26 for (int i = 0; i < n; i++) { G[i].clear(); id[i] = -1; }
27 for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) if (i != j && v[i][j] < M)
28 G[i].push_back(j);
29 dfs(0);
30 for (int i = 0; i < n; i++) if (id[i] == -1) return 1;
31 return 0;
32 }
33
34 int main() {
35 // freopen("case.in", "r", stdin);
36 while (scanf("%d", &n) == 1) {
37 int L = 0, R = 0;
38 for (int i = 0; i < n; i++)
39 for (int j = 0; j < n; j++) {
40 scanf("%d", &v[i][j]);
41 R = max(R, v[i][j]);
42 }
43
44 while (L <= R) {
45 int M = (L + R) / 2;
46 if (check(M)) L = M + 1;
47 else R = M - 1;
48 }
49 printf("%d\n", R);
50 }
51 }
Problem F 牧场物语
题意:略
题解:dp[i][j][k]表示走了i步,然后第一次走停留在j行,第二次走停留在k行,为什么要这样呢?首先他要求的是最短路,所以一定是dp(否则可以用网络流)。然后就是当步数和行数确定的时候对应的列也是确定的。状态转移就四种,下下,下右,右下,右右。
1 /*zhen hao*/
2 #include <cstdio>
3 #include <iostream>
4 using namespace std;
5
6 #define lson l, m, rt << 1
7 #define rson m + 1, r, rt << 1 | 1
8 #define ll long long
9 #define xx first
10 #define yy second
11
12 const int maxn = 110;
13 const ll inf = 1LL << 60;
14 ll dp[maxn << 1][maxn][maxn], v[maxn][maxn];
15
16 void init(int n) {
17 for (int i = 0; i < 2 * n; i++)
18 for (int j = 0; j < n; j++)
19 for (int k = 0; k < n; k++)
20 dp[i][j][k] = -inf;
21 }
22
23 int main() {
24 // freopen("case.in", "r", stdin);
25 int n;
26 while (scanf("%d", &n) == 1) {
27 for (int i = 0; i < n; i++)
28 for (int j = 0; j < n; j++)
29 scanf("%I64d", &v[i][j]);
30
31 init(n);
32 dp[0][0][0] = v[0][0];
33
34 for (int i = 0; i < 2 * n - 2; i++)
35 for (int j = 0; j < n; j++)
36 for (int k = 0; k < n; k++) if (dp[i][j][k] != -inf) {
37 int jj = i - j, kk = i - k;
38 // cout << j << ‘ ‘ << jj << ‘ ‘ << k << ‘ ‘ << kk << endl;
39 if (j != n - 1 && k != n - 1) {
40 if (j != k) dp[i + 1][j + 1][k + 1] = max(dp[i + 1][j + 1][k + 1], dp[i][j][k] + v[j + 1][jj] + v[k + 1][kk]);
41 else dp[i + 1][j + 1][k + 1] = max(dp[i + 1][j + 1][k + 1], dp[i][j][k] + v[j + 1][jj]);
42 }
43 if (j != n - 1 && kk != n - 1) {
44 if (j + 1 != k) dp[i + 1][j + 1][k] = max(dp[i + 1][j + 1][k], dp[i][j][k] + v[j + 1][jj] + v[k][kk + 1]);
45 else dp[i + 1][j + 1][k] = max(dp[i + 1][j + 1][k], dp[i][j][k] + v[j + 1][jj]);
46 }
47 if (jj != n - 1 && k != n - 1) {
48 if (j != k + 1) dp[i + 1][j][k + 1] = max(dp[i + 1][j][k + 1], dp[i][j][k] + v[j][jj + 1] + v[k + 1][kk]);
49 else dp[i + 1][j][k + 1] = max(dp[i + 1][j][k + 1], dp[i][j][k] + v[j][jj + 1]);
50 }
51 if (jj != n - 1 && kk != n - 1) {
52 if (j != k) dp[i + 1][j][k] = max(dp[i + 1][j][k], dp[i][j][k] + v[j][jj + 1] + v[k][kk + 1]);
53 else dp[i + 1][j][k] = max(dp[i + 1][j][k], dp[i][j][k] + v[j][jj + 1]);
54 }
55 }
56 printf("%I64d\n", dp[2 * n - 2][n - 1][n - 1]);
57 }
58 return 0;
59 }
Problem G 国王的出游
题意:略
题解:这道题咋一眼看好像要离散化模拟什么的,实际上所有的线状区域长度不超过10 ^ 5就说明可以直接进行bfs,对于找点可以放在一个数组然后二分查找一下有没有这个点即可。
1 /*zhen hao*/
2 #include <cstdio>
3 #include <vector>
4 #include <cstring>
5 #include <queue>
6 #include <algorithm>
7 using namespace std;
8
9 #define lson l, m, rt << 1
10 #define rson m + 1, r, rt << 1 | 1
11 #define ll long long
12 #define xx first
13 #define yy second
14
15 typedef pair<int,int> pii;
16 const int maxn = 1e5 + 10;
17 int sx, sy, ex, ey, cnt;
18 pii p[maxn];
19 bool vis[maxn];
20
21 struct Node {
22 int x, y, d;
23 Node(int x=0,int y=0, int d=0) : x(x), y(y), d(d) {}
24 };
25
26 int bfs() {
27 queue<Node> q;
28 q.push(Node(sx, sy, 0));
29 memset(vis, false, sizeof vis);
30 pii tp = make_pair(sx, sy);
31 int k = lower_bound(p, p + cnt, tp) - p;
32 vis[k] = 1;
33 while (!q.empty()) {
34 Node u = q.front(); q.pop();
35 if (u.x == ex && u.y == ey) return u.d;
36 for (int i = -1; i <= 1; i++) for (int j = -1; j <= 1; j++) if (i != 0 || j != 0) {
37 int nx = u.x + i, ny = u.y + j;
38 tp = make_pair(nx, ny);
39 k = lower_bound(p, p + cnt, tp) - p;
40 if (p[k] != tp || vis[k]) continue;
41 vis[k] = 1;
42 q.push(Node(nx, ny, u.d + 1));
43 }
44 }
45 return -1;
46 }
47
48 int main() {
49 // freopen("case.in", "r", stdin);
50 while (scanf("%d%d%d%d", &sx, &sy, &ex, &ey) == 4) {
51 int x;
52 scanf("%d", &x);
53 cnt = 0;
54 for (int i = 0; i < x; i++) {
55 int r, a, b;
56 scanf("%d%d%d", &r, &a, &b);
57 for (int j = a; j <= b; j++)
58 p[cnt++] = make_pair(r, j);
59 }
60 p[cnt++] = make_pair(sx, sy);
61 p[cnt++] = make_pair(ex, ey);
62 sort(p, p + cnt);
63
64 printf("%d\n", bfs());
65
66 }
67 return 0;
68 }
Problem H 第十四个目标
题意:略
题解:dp+离散化用二分即可。
Problem I 中位数
题意:略
题解:据说是主席树,然而并不会,先留个坑。
标签:
原文地址:http://www.cnblogs.com/zhenhao1/p/5459618.html