Facebook Hacker Cup 2016 Qualification Round High Security

探讨一种高效算法,用于确定最少数量的守卫以确保所有关键区域得到监控。通过分析不同场景,如连续空位及障碍物间的空位,来优化守卫的布置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


High Security 25 points
Choose Output
No output file selected

A top-secret algorithmic research facility has decided to up its security by hiring guards to keep watch over the premises. After all, they don't want anyone sneaking in and learning the answers to questions such as "does P = NP?" and "what are the solutions to the 2016 Facebook Hacker Cup problems?".

When viewed from above, the facility can be modeled as a grid G with 2 rows and N columns. The jth cell in the ith row is either empty (represented by Gi,j = ".") or occupied by a building (Gi,j= "X"), and the grid includes at least one empty cell.

Guards may be potentially stationed in any of the empty cells. A guard can see not only their own cell, but also all contiguous empty cells in each of the 4 compass directions (up, down, left, and right) until the edge of the grid or a building. For example, in the grid below, the guard ("G") can see every cell marked with an asterisk ("*"):

.*.X.X..
*G*****X

What is the minimum number of guards required such that every empty cell in the grid can be seen by at least one of them?

Input

Input begins with an integer T, the number of facilities that need guarding. For each facility, there is first a line containing the integer N. The next line contains the grid cells G1,1 to G1,N in order. The third line contains the grid cells G2,1 to G2,N in order.

Output

For the ith facility, print a line containing "Case #i: " followed by the number of guards required to guard the facility.

Constraints

1 ≤ T ≤ 200 
1 ≤ N ≤ 1,000 

Explanation of Sample

In the first case, one solution is to place three guards as follows:

.G.X.XG.
....G..X
Example input  ·  Download
Example output  ·  Download
5
8
...X.X..
.......X
5
.X.X.
.XXX.
7
.....X.
.X.....
9
..X.X.X..
..X...X.X
15
.X..........X..
.X...XX.X.X....
Case #1: 3
Case #2: 3
Case #3: 2
Case #4: 5
Case #5: 6




题意:给个2×N的矩阵,'.'表示可以站守卫,‘X'表示墙,守卫可以查看上下左右4个方向,问至少放多少守卫,

视线可以覆盖所有’.'位置。

思路:如果N×N的话,可以用二分图,这个才2,不用那样。

如果是两行连续的

....

..

不论是否等长,都需要至少2个守卫才能全部覆盖。

如果是

X.X

. . .

这种两个墙之间有且只有一个空位,如果对面有空位那就在对面放守卫,因为对面放守卫,遇到上面这种情况,

不仅可以覆盖当前位置还可以覆盖下一行的一段,除非对面没位置,才在当前位置放守卫。

即使遇到下面这种情况

X.X

X.X

上面的理论也是成立的。

当把这种仅有一个的空缺填满了,剩下的就是第一种情况,两行不等长的连续,或者仅有一行连续。这种都是

一行一个守卫。

这样分情况做就可以了。

<pre name="code" class="cpp">#include <bits/stdc++.h>

typedef long long ll;
using namespace std;
char mp[2][N];
bool flag[2][N];
void run()
{
  int n, ans = 0;
  scanf("%d", &n);
  scanf("%s", mp[0]);
  scanf("%s", mp[1]);
  memset(flag, 0, sizeof(flag)); 
//下面的二重循环是为了填补X.X的情况
  for (int i = 0; i < n; i++)
    for (int bt = 0; bt < 2; bt++)
    if (mp[bt][i] == '.' && !flag[bt][i])
    {
      if (i - 1 < 0 || mp[bt][i-1] == 'X')
        if (i + 1 >= n || mp[bt][i+1] == 'X')
        {
          if (mp[bt^1][i] == '.')
          {
            for (int j = 1; j <= n; j++)
              if (i + j < n && mp[bt^1][i+j] == '.')//向右填充覆盖区域
                flag[bt^1][i+j] = 1;
              else
                break;
            for (int j = 1; j <= n; j++)
              if (i - j >= 0 && mp[bt^1][i - j] == '.')//向左填充覆盖区域
                 flag[bt^1][i-j] = 1;
              else
                 break;
          }         
          ans++;  
          flag[bt^1][i] = flag[bt][i] = 1;
          
        }
    }
    // 填充连续行
    for (int i = 0; i < 2; i++)
      for (int j = 0; j < n; j++)
        if (mp[i][j] == '.' && !flag[i][j])
        {
          ans++;
          for (int k = j; k < n; k++)
            if (mp[i][k] == 'X')
              break;
            else
              flag[i][k] = 1;
          if (mp[i^1][j] == '.' && !flag[i^1][j])
          {
            flag[i^1][j] = 1;
          }
        }
    printf("%d\n", ans);
}
int main()
{
    int T, cas = 1;
    scanf("%d", &T);
    while (T--)
    {
      printf("Case #%d: ", cas++);
      run();
    }

    return 0; 
}


 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值