P7749 [COCI2013-2014#2] MISA 题解
P7749 [COCI2013-2014#2] MISA 题解
思路:先求出 Mirko 没入座时人们的握手次数,再枚举 Mirko 入座的位置,若这个座位为空,那么计算 Mirko 在这个位置入座的握手次数,求出最大值。否则跳过。最后输出 Mirko 可以握手的最大次数加上 Mirko 没入座的所有人的握手次数。
对于刚开始 Mirko 没入座时所有人的握手次数,可以把每个人的的握手次数相加,最后除以 2 。因为握手时双向的,计算过程中,每一次握手都被计算了两次,所以最后要除以 2 。
还有两个小优化:
- 若会场坐满了,可以直接输出,不用枚举
Mirko入座的位置,因为他无处可坐了。 - 如果枚举到某一时刻,
Mirko可以握手的人数为8,可直接输出答案,因为一个人最多与周围八个人握手。
Code:
#include <stdio.h>
#define clac(r, c) (flag[r - 1][c - 1] + flag[r - 1][c] + flag[r - 1][c + 1] + flag[r][c - 1] + flag[r][c + 1] + flag[r + 1][c - 1] + flag[r + 1][c] + flag[r + 1][c + 1])//计算握手的人数
#define max(a, b) ((a) > (b) ? (a) : (b))//手写max函数
bool bol = true, flag[64][64];
int n, m, sum, ans;
char ch[64][64];
int main() {
scanf("%d%d", &n, &m);
getchar();
for(int i = 1; i <= n; ++i) scanf("%s", ch[i] + 1);
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
bol &= flag[i][j] = (ch[i][j] == 'o');//其实这里这样写是为了偷懒,可以写成flag[i][j] = (ch[i][j] == 'o'); if(!flag[i][j]) bol = false;
//计算Mirko没入座时人们的握手情况
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
if(flag[i][j]) sum += clac(i, j);
sum /= 2;
if(bol) return 0 * printf("%d", sum);//第一种优化
//枚举Mirko的位置
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j) {
if(!flag[i][j]) ans = max(ans, clac(i, j));//i行j列位置Mirko的握手次数
if(ans == 8) return 0 * printf("%d", sum + ans);//第二种优化
}
printf("%d", sum + ans);
return 0;
}