A题:
rook的话如果同行同列就一次,否则两次。
bishop,首先如果一个在白色位置,另外一个在黑色位置是不可达的。
否则再一条对角线上就一次,其余位置两次。
king,bfs()一次求出答案。
AC代码:
#include <cstdio> #include <cstring> const int MAX_NUMBER = 1007; struct Point { int x, y, steps; }; int n; int start_x, start_y, end_x, end_y; int ans_1, ans_2, ans_3; int step[8][2] = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}}; int vis[10][10]; struct Point point[MAX_NUMBER]; void bfs() { memset(vis, 0, sizeof(vis)); point[0].x = start_x; point[0].y = start_y; vis[start_x][start_y] = 1; int front = 0; int rear = 1; while (front < rear) { struct Point cnt_point = point[front]; int cnt_x = cnt_point.x; int cnt_y = cnt_point.y; if (cnt_x == end_x && cnt_y == end_y) { ans_3 = cnt_point.steps; return ; } for (int i = 0; i < 8; i++) { int next_x = cnt_x + step[i][0]; int next_y = cnt_y + step[i][1]; if (next_x >= 1 && next_x <= 8 && next_y >= 1 && next_y <= 8 && !vis[next_x][next_y]) { vis[next_x][next_y] = 1; point[rear].x = next_x; point[rear].y = next_y; point[rear].steps = cnt_point.steps + 1; rear++; } } front++; } } int main() { scanf("%d%d%d%d", &start_x, &start_y, &end_x, &end_y); if (start_x == end_x || start_y == end_y) { ans_1 = 1; } else { ans_1 = 2; } if ((start_x + start_y) % 2 != (end_x + end_y) % 2) { ans_2 = 0; } else if (start_x + start_y == end_x + end_y || start_x - start_y == end_x - end_y) { ans_2 = 1; } else { ans_2 = 2; } bfs(); printf("%d %d %d\n", ans_1, ans_2, ans_3); return 0; }
B题:
O(n ^ 2),枚举判断一个集合是不是另一个集合的子集或者真子集。
如果是真子集的话,那么超集就不可能赢。如果是想等的话两个都不可能赢,其他情况可能赢。
AC代码:
#include <cstdio> #include <cstring> #include <vector> #include <algorithm> #include <set> using namespace std; const int MAX_NUMBER = 107; vector<int> player[MAX_NUMBER]; set<int> player_set[MAX_NUMBER]; int vis[MAX_NUMBER], ans[MAX_NUMBER]; int player_number; int main() { memset(vis, 0, sizeof(vis)); scanf("%d", &player_number); for (int i = 1; i <= player_number; i++) { int cnt_number; scanf("%d", &cnt_number); for (int j = 1; j <= cnt_number; j++) { int temp; scanf("%d", &temp); player_set[i].insert(temp); player[i].push_back(temp); } } int n = 1; memset(ans, -1, sizeof(ans)); for (int i = 1; i <= player_number; i++) { for (int j = i + 1; j <= player_number; j++) { int flag = 0; if (player[i].size() == player[j].size()) { for (int k = 0; k < player[j].size(); k++) { if (!player_set[i].count(player[j][k])) { flag = 1; break; } } if (!flag) { ans[i] = ans[j] = 0; } } else if (player[i].size() < player[j].size()) { for (int k = 0; k < player[i].size(); k++) { if (!player_set[j].count(player[i][k])) { flag = 1; break; } } if (!flag) { ans[j] = 0; } } else { for (int k = 0; k < player[j].size(); k++) { if (!player_set[i].count(player[j][k])) { flag = 1; break; } } if (!flag) { ans[i] = 0; } } } } for (int i = 1; i <= player_number; i++) { if (ans[i] == -1) { printf("YES\n"); } else { printf("NO\n"); } } return 0; }
C题:
贪心。
每次对各种颜色有的手套数进行排序,颜色最少的和颜色最多的去匹配。
匹配到最后无法匹配的只能和自己匹配了。
但是这种贪心不是正确的,比如说颜色1:7个人,颜色2:5个人,颜色3:1个人,颜色4:3个人。
按这种贪心的话,
先匹配3- 1,1-3,然后4-1,1-4,4-1,1-4,接下来再1-2,2-1,1-2,2-1,1-2,2-1
最后颜色2还剩下4只手套,只能是2-2,2-2,但是有一种明显更好的方式,比如说最后的2和3-1的随便一个进行交换,答案会多出来。
所有我的做法是先贪心,贪心完后看是否能不能和前面的手套进行交换使结果更好,如果能的话肯定要交换,得出最后的答案。
AC代码:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAX_NUMBER = 100007; struct Color { int color, number; }; struct Ans { int x, y; }; struct Ans ans[MAX_NUMBER]; bool cmp(struct Color a, struct Color b) { return a.number < b.number; } struct Color color[MAX_NUMBER]; int vis[MAX_NUMBER]; int color_number, ans_number, children, pre_number, diff; void deal() { pre_number = color_number; sort(color + 1, color + color_number + 1, cmp); color_number = 0; for (int i = 1; i <= pre_number; i++) { if (color[i].number != 0) { color[++color_number].color = color[i].color; color[color_number].number = color[i].number; } } if (color_number >= 2) { for (int i = 0; i < color[1].number; i += 2) { ans[ans_number].y = color[1].color; ans[ans_number].x = color[color_number].color; ans_number++; ans[ans_number].x = color[1].color; ans[ans_number].y = color[color_number].color; ans_number++; } color[color_number].number -= color[1].number; color[1].number = 0; diff = ans_number; } else if (color_number == 1){ for (int i = 0; i < color[1].number; i += 2) { ans[ans_number].x = color[1].color; ans[ans_number].y = color[1].color; ans_number++; } color_number = 0; } } int main() { int m; scanf("%d%d", &children, &m); memset(color, 0, sizeof(color)); memset(vis, 0, sizeof(vis)); color_number = 0; for (int i = 1; i <= m; i++) { color[i].color = i; } for (int i = 1; i <= children; i++) { int temp; scanf("%d", &temp); if (!vis[temp]) { vis[temp] = 1; color[temp].number = 2; } else { color[temp].number += 2; } } color_number = m; while (1) { deal(); if (color_number == 0) { break; } } int final_result = diff; if (ans_number != diff) { int cnt_number = 0; for (int i = 0; i < diff && cnt_number < ans_number - diff; i++) { if (ans[i].x != ans[diff + cnt_number].x && ans[i].y != ans[diff + cnt_number].y) { int temp = ans[diff + cnt_number].x; ans[diff + cnt_number].x = ans[i].x; ans[i].x = temp; final_result++; cnt_number++; } } } printf("%d\n", final_result); for (int i = 0; i < ans_number; i++) { printf("%d %d\n", ans[i].x, ans[i].y); } return 0; }D题:
没看懂题目意思= =