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题:
没看懂题目意思= =