Pass-Muraille——魔术师穿墙 贪心

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;
}

参考自:https://blog.csdn.net/qq_40507857/article/details/84837879?utm_medium=distribute.pc_relevant.none-task-blog-baidulandingword-4&spm=1001.2101.3001.4242

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值