这道题就两个步骤:

1.找联通块个数:判断是否符合标准并且找联通块个数

我用的广搜实现的,思路挺简单的:

先找一个联通块的端点,根据题中的定义,一个联通块的端点,周围所不是座位的个数(指上下左右),只有3个,或者4个(只有一个点的情况),对这个点进行搜索,标记,然后扩展,遇到下一个座位,就走,走过就标记,并对联通块计数的加一,最后返回走的联通块的座位数。

那么,如何判断这不是正确的教室呢? 因为我们对搜过的都进行了标记,所以我们可以判断有没有是座位却没有被标记的情况,因为只有有端点的才能是符合标准的,没有对这一块进行搜索,那就是没有端点,也就不符合了。又因为我们从端点开始搜索的,那就说明每一个点能扩展的点,就只有一个点(本来应该是两个的,但是因为前一个点被标记了,也不能走,相当于只能扩展一个),我们可以进行统计每一个点能扩展的点,如果大于1,就也是错的。

2.对方法数目进行计算:利用乘法原理

啊本人不会画图就手打了吧

对于这一块的话OOOOOOO ,第一个可以填k个学校,那么后面一个就只能填k-1学校,后面的也是,以此类推,可以得到每一个联通块的方法数目为: k*(s-1)^(k-1) ,其中size为联通块大小,然后对于所有联通块一起的方法书,也一样,全乘起来就okk。

剩下的细节之类的都在代码里面了,码代上上代码:

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. long long dx[] = {1 , 0 , -1 , 0} , dy[] = {0 , -1 , 0 , 1}; //上下移动
  4. long long n , m , k , sum , p = 998244353; //sum是联通块个数
  5. long long s[1000010]; //存储每一个联通块的大小
  6. char a[1010][1010]; //存储图
  7. bool f; //判断是否座位只联通一个座位
  8. bool vis[1010][1010]; //标记
  9. struct node{
  10. long long c , d;
  11. };
  12. long long ksm(long long x , long long y){ //快速幂,怕超时,没去试pow(x,y)会不会超时
  13. long long ret = 1;
  14. y %= p;
  15. x %= p;
  16. while(y){
  17. if(y % 2 == 1){
  18. ret = ret * x;
  19. ret %= p;
  20. }
  21. x = x % p * x % p;
  22. x %= p;
  23. y /= 2;
  24. }
  25. return ret;
  26. }
  27. long long pd(long long x , long long y){ //统计周围不是座位的个数
  28. long long sssum = 0;
  29. if(a[x + 1][y] != 'O') sssum++;
  30. if(a[x - 1][y] != 'O') sssum++;
  31. if(a[x][y + 1] != 'O') sssum++;
  32. if(a[x][y - 1] != 'O') sssum++;
  33. return sssum;
  34. }
  35. long long bfs(long long x , long long y){ //广搜
  36. long long t = 1;
  37. queue<node> q;
  38. node nod;
  39. nod.c = x;
  40. nod.d = y;
  41. q.push(nod);
  42. node now;
  43. vis[x][y] = 1;
  44. while(!q.empty()){
  45. now = q.front();
  46. q.pop();
  47. long long tt = 0;
  48. for(int v = 0; v <= 3; v++){
  49. int nx = now.c + dx[v] , ny = now.d + dy[v];
  50. if(!vis[nx][ny] && a[nx][ny] == 'O'){
  51. tt++; //统计这个点能扩展的点的个数
  52. t++;
  53. vis[nx][ny] = 1;
  54. nod.c = nx;
  55. nod.d = ny;
  56. q.push(nod);
  57. }
  58. }
  59. if(tt > 1){ //大于一个就说明不符合要求,并且不能用不等于,因为最后一个点是不能扩展的,就是0,但是合法
  60. f = true;
  61. return 0; //不符合直接返回
  62. }
  63. }
  64. return t;
  65. }
  66. int main(){
  67. cin >> n >> m >> k;
  68. for(int i = 1; i <= n + 5; i++)
  69. for(int j = 1; j <= m + 5; j++) a[i][j] = 'X'; //初始化
  70. for(int i = 1; i <= n; i++)
  71. for(int j = 1; j <= m; j++) cin >> a[i][j];
  72. for(int i = 1; i <= n; i++)
  73. for(int j = 1; j <= m; j++){
  74. if(a[i][j] == 'O' && !vis[i][j]){ //找端点。为什么有vis?因为一个联通块有两个端点我们只需要搜索一次就OK
  75. int ha = pd(i , j);
  76. if(ha < 3) continue; //不是端点
  77. f = false;
  78. sum++; //块数加一
  79. s[sum] = bfs(i , j);
  80. if(f){ //不符合条件
  81. cout << 0;
  82. return 0;
  83. }
  84. }
  85. }
  86. for(int i = 1; i <= n; i++) //找没搜过却是座位的情况,也是错误的
  87. for(int j = 1; j <= m; j++)
  88. if(a[i][j] == 'O' && !vis[i][j]){
  89. cout << 0;
  90. return 0;
  91. }
  92. long long ans = 1;
  93. k %= p;
  94. for(int i = 1; i <= sum; i++){
  95. ans *= k % p * ksm((k - 1) , s[i] - 1) % p; //记得每一次都mod一下,不然会只有30分的,别问我怎么知道的,调了半天的
  96. ans %= p;
  97. }
  98. cout << ans % p;
  99. return 0;
  100. }
  101. /*
  102. 7 7 99
  103. XOOXOOO
  104. XOXXXXO
  105. XOOXOXO
  106. XXXXOXO
  107. XOOXOOO
  108. XXOXXXX
  109. XOOXOOO
  110. */

啊就这么多了,一道不错的搜索题

洛谷 P6582 【座位调查】的更多相关文章

  1. 洛谷P1386座位安排

    座位安排 今天,在机房里做了这道题目,我来整理一下思路. 首先读懂题意,这n个人是不需要按1到n来一次安排的,也就是说你可以先安排任意一个人. 那么有一种很好排除的情况,那就是对于大于等于i的作为的需 ...

  2. 洛谷——P2071 座位安排 seat.cpp/c/pas

    P2071 座位安排 seat.cpp/c/pas 题目背景 公元二零一四年四月十七日,小明参加了省赛,在一路上,他遇到了许多问题,请你帮他解决. 题目描述 已知车上有N排座位,有N*2个人参加省赛, ...

  3. 【二分图】【最大匹配】【匈牙利算法】洛谷 P2071 座位安排 seat.cpp/c/pas

    ∵每个座位可以坐俩人,所以拆点最大匹配. #include<cstdio> #include<vector> #include<cstring> using nam ...

  4. 洛谷P2071 座位安排

    题目背景 公元二零一四年四月十七日,小明参加了省赛,在一路上,他遇到了许多问题,请你帮他解决. 题目描述 已知车上有N排座位,有N*2个人参加省赛,每排座位只能坐两人,且每个人都有自己想坐的排数,问最 ...

  5. 洛谷 P2071 座位安排 seat.cpp/c/pas

    P2071 座位安排 seat.cpp/c/pas 题目背景 公元二零一四年四月十七日,小明参加了省赛,在一路上,他遇到了许多问题,请你帮他解决. 题目描述 已知车上有N排座位,有N*2个人参加省赛, ...

  6. 洛谷P1407 工资

    洛谷P1407 工资 本题地址:http://www.luogu.org/problem/show?pid=1407 题目描述 有一家世界级大企业,他们经过调查,发现了一个奇特的现象,竟然在自己的公司 ...

  7. 【洛谷1607】【USACO09FEB】庙会班车

    题面 题目描述 逛逛集市,兑兑奖品,看看节目对农夫约翰来说不算什么,可是他的奶牛们非常缺乏锻炼--如果要逛完一整天的集市,他们一定会筋疲力尽的.所以为了让奶牛们也能愉快地逛集市,约翰准备让奶牛们在集市 ...

  8. 洛谷 P2835 刻录光盘

    题目链接 https://www.luogu.org/problemnew/show/P2835 题目描述 在JSOI2005夏令营快要结束的时候,很多营员提出来要把整个夏令营期间的资料刻录成一张光盘 ...

  9. 洛谷NOIp热身赛题解

    洛谷NOIp热身赛题解 A 最大差值 简单树状数组,维护区间和.区间平方和,方差按照给的公式算就行了 #include<bits/stdc++.h> #define il inline # ...

随机推荐

  1. Java实现 LeetCode 770 基本计算器 IV(暴力+分析题)

    770. 基本计算器 IV 给定一个表达式 expression 如 expression = "e + 8 - a + 5" 和一个求值映射,如 {"e": ...

  2. Java实现 LeetCode 204 计数质数

    204. 计数质数 统计所有小于非负整数 n 的质数的数量. 示例: 输入: 10 输出: 4 解释: 小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 . class Solutio ...

  3. Java实现 LeetCode 202 快乐数

    202. 快乐数 编写一个算法来判断一个数是不是"快乐数". 一个"快乐数"定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过 ...

  4. Java中IO软件包的详细介绍

    一.Java Io流 Java Io流的概念 java的io是实现输入和输出的基础,可以方便的实现数据的输入和输出操作.在java中把不同的输入/输出源(键盘,文件,网络连接等)抽象表述为" ...

  5. 第四届蓝桥杯JavaC组省赛真题

    解题代码部分来自网友,如果有不对的地方,欢迎各位大佬评论 题目1.猜年龄 题目描述 美国数学家维纳(N.Wiener)智力早熟,11岁就上了大学.他曾在1935~1936年应邀来中国清华大学讲学. 一 ...

  6. java中PipedStream管道流通信详细使用(详解)

    多线程使用PipedStream 通讯 Java 提供了四个相关的管道流,我们可以使用其在多线程进行数据传递,其分别是 类名 作用 备注 PipedInputStream 字节管道输入流 字节流 Pi ...

  7. wtf.sh-150

    前言: 最近在刷ctf题,在理解了大佬们的wp后自己做完之后,从头到尾把思路过了一遍,做次记录为以后复习和打比赛做准备,同时也希望能帮到别人. 0x01 进入网址,发现是一个论坛,有注册,登录和发表的 ...

  8. 聊聊依赖注入注解@Resource和@Autowired

    1. 前言 @Resource和@Autowired注解都可以在Spring Framework应用中进行声明式的依赖注入.而且面试中经常涉及到这两个注解的知识点.今天我们来总结一下它们. 2. @R ...

  9. 重学 Java 设计模式:实战装饰器模式(SSO单点登录功能扩展,增加拦截用户访问方法范围场景)

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 对于代码你有编程感觉吗 很多人写代码往往是没有编程感觉的,也就是除了可以把功能按照固 ...

  10. php实现登录失败次数限制

    需求:同一个账号在同一个IP地址连续密码输错一定次数后,这个账号是会被锁定30分钟的. 实现思路: 需要一个表(user_login_info)负责记录用户登录的信息,不管登录成功还是失败都记录.并且 ...