Pass-Muraille
Description
In modern day magic shows, passing through walls is very popular in which a magician performer passes through several walls in a predesigned stage show. The wall-passer (Pass-Muraille) has a limited wall-passing energy to pass through at most k walls in each wall-passing show. The walls are placed on a grid-like area. An example is shown in Figure 1, where the land is viewed from above. All the walls have unit widths, but different lengths. You may assume that no grid cell belongs to two or more walls. A spectator chooses a column of the grid. Our wall-passer starts from the upper side of the grid and walks along the entire column, passing through every wall in his way to get to the lower side of the grid. If he faces more than k walls when he tries to walk along a column, he would fail presenting a good show. For example, in the wall configuration shown in Figure 1, a wall-passer with k = 3 can pass from the upper side to the lower side choosing any column except column 6.
Given a wall-passer with a given energy and a show stage, we want to remove the minimum number of walls from the stage so that our performer can pass through all the walls at any column chosen by spectators.
Input
The first line of the input file contains a single integer t (1 <= t <= 10), the number of test cases, followed by the input data for each test case. The first line of each test case contains two integers n (1 <= n <= 100), the number of walls, and k (0 <= k <= 100), the maximum number of walls that the wall-passer can pass through, respectively. After the first line, there are n lines each containing two (x, y) pairs representing coordinates of the two endpoints of a wall. Coordinates are non-negative integers less than or equal to 100. The upper-left of the grid is assumed to have coordinates (0, 0). The second sample test case below corresponds to the land given in Figure 1.
Output
There should be one line per test case containing an integer number which is the minimum number of walls to be removed such that the wall-passer can pass through walls starting from any column on the upper side.
Sample Input
2
3 1
2 0 4 0
0 1 1 1
1 2 2 2
7 3
0 0 3 0
6 1 8 1
2 3 6 3
4 4 6 4
0 5 1 5
5 6 7 6
1 7 3 7
Sample Output
1
1
Hint
Walls are parallel to X.
题意: 给出n条墙的两端的坐标,在给出一个k,代表魔术师一次性能够穿过最大的墙的厚度,但是有的地方的墙的厚度超过了k,现要我们求移除最少的墙使得魔术师能够通过任意的位置。
题解: 这题是贪心的思想。我们将每个位置的墙的厚度算出来,如果发现某个位置的墙的厚度超过了k,这时候我们就从该列(该位置)开始,寻找从该列到最右侧的最长的墙,找到这条墙并把它删掉,如此,从该列开始后面的列的墙体的厚度都减掉了1,如果该列的厚度仍然大于k,继续重复上面的操作。(可以结合代码注释理解)
c++ AC代码
#include<cstring>
#include<iostream>
#include<cstdio>
using namespace std;
const int MAX = 110;
int l[MAX],r[MAX],wall[MAX],mark[MAX];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(wall,0,sizeof(wall));
memset(mark,0,sizeof(mark));
int n,k;
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++)
{
int m1,m2; // 两个无用的变量(代表的是墙的所在行)
scanf("%d%d%d%d",l+i,&m1,r+i,&m2);
if(l[i] > r[i]) swap(l[i],r[i]);
for(int j=0;j<105;j++)
{
if(l[i]<=j && j<=r[i]) // 如果在第j列这个位置存在墙体
wall[j]++; // 第j列的墙体厚度增加1
else if(j>r[i]) break; // 一次只输入了一条墙,r[i]后面没有了,就不用管了
}
}
int ans=0;
int maxright,mr;
for(int i=0;i<105;i++) // 墙的长度
{
while(wall[i] > k)
{
maxright = 0;
for(int j=0;j<n;j++)
if(l[j] <= i && i <= r[j] && !mark[j]) // 找从该列开始右边最长的墙
if(maxright < r[j])
{
maxright = r[j];
mr = j;
}
mark[mr] = 1; // 表示该条墙已经被删除了,同时答案加1
ans++;
for(int z=i;z<=maxright;z++) // 墙体厚度减1
wall[z]--;
}
}
printf("%d\n",ans);
}
return 0;
}