1. 问题描述:

给定一个 N×M 的棋盘,有一些格子禁止放棋子。问棋盘上最多能放多少个不能互相攻击的骑士(国际象棋的"骑士",类似于中国象棋的"马",按照"日"字攻击,但没有中国象棋"别马腿"的规则)。

输入格式

第一行包含三个整数 N,M,T,其中 T 表示禁止放置的格子的数量。接下来 T 行每行包含两个整数 x 和 y,表示位于第 x 行第 y 列的格子禁止放置,行列数从 1 开始。

输出格式

输出一个整数表示结果。

数据范围

1 ≤ N,M ≤ 100

输入样例:

2 3 0

输出样例:

4
来源:378. 骑士放置 - AcWing题库

2. 思路分析:

分析题目可以知道我们需要求解在图中最多可以选择多少个点使得选出的点两两是不能够相互攻击,属于最大独立集的问题,最大独立集:从一个图中选出最多的点使得选出的点之间是没有边的,最大团:从一个图中选出若干个点使得任意两点都是有边的,最大独立集与最大团是互补的关系,原图的最大独立集就是补图的最大团;在二分图中求解最大独立集等价于我们需要在图中去掉最少的点使得所有的边都破坏掉,等价于求解最小点覆盖,等价于求解最大匹配,但是还需要验证一下是否是二分图,一个图是二分图等价于染色法不存在矛盾,我们可以将每一个格子看成是一个点,把相互可以攻击的位置连一条边,当前格子可以攻击八个不同的方向("日"字型)可以隔一个格子进行染色,可以发现相互攻击的位置都是不同的颜色,也即染色的过程中不存在矛盾那么是二分图,在二分图中有一个比较重要的结论:最大独立集 = 总点数 - 最小点覆盖 = 总点数 - 最大匹配数,所以我们可以使用匈牙利算法求解最大匹配数即可,最终答案为:n * m - k - res,其中k为坏掉的格子数量,res为最大匹配的数目,因为是二维平面所以match数组的每一个元素要存储匹配的坐标,对于python可以使用声明一个二维列表,列表的每一个元素为元组类型,c++语言可以声明为pair类型。

其实举一个例子就比较好理解了,在2 * 3的矩阵中,坏掉的格子数量为0,那么可以放置最多四个不会相互攻击的骑士,其实是在所有相互攻击的边中去掉最小的点,使得所有的相互攻击的边全部破坏掉,最终这些点就不会相互攻击了,而这些去掉的点的位置是不能够填骑士的,所以要减去这些点的数量:

并且类似于之前的棋盘覆盖的题目我们也是枚举奇数格子或者偶数格子即可,这样相当于是枚举一个方向。

3. 代码如下:

c++:

#include <cstring>
#include <iostream>
#include <algorithm>#define x first
#define y secondusing namespace std;typedef pair<int, int> PII;const int N = 110;int n, m, k;
PII match[N][N];
bool g[N][N], st[N][N];int dx[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
int dy[8] = {1, 2, 2, 1, -1, -2, -2, -1};bool find(int x, int y)
{for (int i = 0; i < 8; i ++ ){int a = x + dx[i], b = y + dy[i];if (a < 1 || a > n || b < 1 || b > m) continue;if (g[a][b]) continue;if (st[a][b]) continue;st[a][b] = true;PII t = match[a][b];if (t.x == 0 || find(t.x, t.y)){match[a][b] = {x, y};return true;}}return false;
}int main()
{cin >> n >> m >> k;for (int i = 0; i < k; i ++ ){int x, y;cin >> x >> y;g[x][y] = true;}int res = 0;for (int i = 1; i <= n; i ++ )for (int j = 1; j <= m; j ++ ){if (g[i][j] || (i + j) % 2) continue;memset(st, 0, sizeof st);if (find(i, j)) res ++ ;}cout << n * m - k - res << endl;return 0;
}

python(最后一个数据爆栈了):

from typing import List
import sysclass Solution:# 枚举8个可以攻击到的方向, 画一下图就比较清楚了pos = [[-2, -1], [-2, 1], [-1, -2], [-1, 2], [1, -2], [1, 2], [2, 1], [2, -1]]def find(self, x: int, y: int, n: int, m: int, st: List[List[int]], match: List[List[tuple]], g: List[List[int]]):for i in range(8):a, b = x + self.pos[i][0], y + self.pos[i][1]# 当前的格子不合法if a < 1 or a > n or b < 1 or b > m or st[a][b] == 1 or g[a][b] == 1: continuest[a][b] = 1if match[a][b][0] == -1 or self.find(match[a][b][0], match[a][b][1], n, m, st, match, g):match[a][b] = (x, y)return Truereturn False# 其实画图比较好理解, 画一个2 * 3的矩阵def process(self):n, m, k = map(int, input().split())g = [[0] * (m + 10) for i in range(n + 10)]for i in range(k):x, y = map(int, input().split())g[x][y] = 1match = [[(-1, -1)] * (m + 10) for i in range(n + 10)]res = 0for i in range(1, n + 1):for j in range(1, m + 1):# 我们只需要枚举奇数格子或者是偶数格子即可, 枚举偶数格子跳过奇数格子, 反过来也是一样的if (i + j) % 2 or g[i][j] == 1: continuest = [[-1] * (m + 10) for i in range(n + 10)]if self.find(i, j, n, m, st, match, g):res += 1return n * m - k - resif __name__ == "__main__":sys.setrecursionlimit(6000)print(Solution().process())

378 骑士放置(最大独立集)相关推荐

  1. 378. 骑士放置——最大独立集+匈牙利算法

    给定一个 N×M 的棋盘,有一些格子禁止放棋子. 问棋盘上最多能放多少个不能互相攻击的骑士(国际象棋的"骑士",类似于中国象棋的"马",按照"日&qu ...

  2. Acwing 378.骑士放置(二分图的最大独立集)

    Acwing 378.骑士放置 题意 给定一个 N×M 的棋盘,有一些格子禁止放棋子. 问棋盘上最多能放多少个不能互相攻击的骑士(国际象棋的"骑士",类似于中国象棋的"马 ...

  3. AcWing 378. 骑士放置(最大独立集)

    题目 给定一个 N*M 的棋盘,有一些格子禁止放棋子. 问棋盘上最多能放多少个不能互相攻击的骑士(国际象棋的"骑士",类似于中国象棋的"马",按照"日 ...

  4. 【ACWing】378. 骑士放置

    题目地址: https://www.acwing.com/problem/content/380/ 给定一个N×MN×MN×M的棋盘,有一些格子禁止放棋子.问棋盘上最多能放多少个不能互相攻击的骑士(国 ...

  5. 骑士放置 最大独立集

    一.内容 给定一个 N*M 的棋盘,有一些格子禁止放棋子.问棋盘上最多能放多少个不能互相攻击的骑士(国际象棋的"骑士",类似于中国象棋的"马",按照" ...

  6. AcWing 378. 骑士放置 题解

    原题链接 题目描述 给定一个 N*M 的棋盘,有一些格子禁止放棋子. 问棋盘上最多能放多少个不能互相攻击的骑士(国际象棋的"骑士",类似于中国象棋的"马",按照 ...

  7. Acwing 378. 骑士放置

    题目描述: 给定一个 N×M 的棋盘,有一些格子禁止放棋子. 问棋盘上最多能放多少个不能互相攻击的骑士(国际象棋的"骑士",类似于中国象棋的"马",按照&quo ...

  8. `Algorithm-Solution` `AcWing` 378. 骑士放置

    link Solution If we add the edge a−ba-ba−b where if a=(x,y)a=(x,y)a=(x,y) then bbb is the endpoint i ...

  9. 算法竞赛——进阶指南——acwing378. 骑士放置 最大独立集

    不能相互攻击.我们把每个点相互攻击的格子连边,就相当于求最大独立点集. 且走日字,起末的(横纵坐标和)一定奇偶性不同.满足二分图的性质 等于n-最大匹配. 建模完毕. #include <bit ...

最新文章

  1. 一个6年iOS程序员的工作感悟,送给还在迷茫的你
  2. 面试题;40个多线程的问题 背1 有用
  3. java tomcat监控_java-jvisualvm远程监控tomcat
  4. Android编译小结(新建android项目)
  5. 7.1 useradd:创建用户
  6. Spring整合ibatis的配置
  7. java pk .net_Java与.Net大PK
  8. 【Python】列表推导式求 100 以内的所有素数
  9. vue里面v-once/ref【获取标签里面的内容】
  10. 探寻 JavaScript 逻辑运算符(与、或)的真谛
  11. sybase 事务 超时返回_事务背景介绍(2):MongoDB中的逻辑会话
  12. 谷歌Chrome浏览器开发者工具教程—基础功能篇
  13. 历史文章之python
  14. mac电脑投屏到小米盒子_苹果手机,小米盒子投屏,连接不上,什么情况?
  15. Lemmatization VS Stemming
  16. 页面http 405错误排查
  17. 测试开发 - 十年磨一剑(序)
  18. 概念模型、逻辑模型及物理模型介绍
  19. (毕业设计资料)基于单片机自行车码表系统设计
  20. BIT计科小学期web前端开发lab1

热门文章

  1. 如何提高项目组成员的会议纪要的记录能力?
  2. 2008服务器多网站设置,win2008服务器iis网站设置
  3. 【ISO14229_UDS刷写】-3-$36诊断服务TransferData理论部分
  4. http://www.xxjp.org/Software/Catalog96/1681.html
  5. Android 自动点击
  6. Office for Mac 2021 正式版发布,版本 16.53
  7. SCI文献引用注意事项
  8. JVM(一)一文读懂Java编译全过程
  9. 【javaWeb微服务架构项目——乐优商城day07】——Elasticsearch介绍和安装及使用(安装kibana,安装ik分词器,Spring Data Elasticsearch,高级查询)
  10. 如何使用站群程序来批量建网站?