acm pku 1230Pass-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.

Source

Tehran 2002 Preliminary

 

 

题目大意:对于已经排列好的n面墙壁,若魔术师最多能一次性穿越k面墙壁,那么至少要移去多少面墙壁才能使魔术师的表演永不失败。

分析:对任意某列墙壁i,若在该列上有icolwall面墙壁,如果icolwall>k,则需要移去icolwall-k面墙壁,而且这移去的icolwall-k面墙壁应当是对接下来的列的影响最大的。

       那么什么样的墙壁对接下来的列影响最大呢?事实上,如果处于某行的某墙从i列算起,剩下的格数越多,则其影响越大。

       在处理这个问题时,有两方面需要特别注意:

l         输入墙的位置col[2]row(输入格式:col[0], row, col[1], row)时,先输入的墙的端点并不一定是墙的起始点,它有可能是终止点;

l         两笔墙可能相邻的,看起来好像是一笔墙,但在删除时,应当作为两面墙壁处理;

 

代码实现:

#include

#include "iostream"

using namespace std;

 

#define N 105

 

int main(void)

{

       int t, n, k, res;

       int wall[N][N], col[2], cn[N], row, icolwall, maxrow, maxcol;

       int i, j, ic, itemp, imax;

 

       cin >> t;

       while(t > 0)

       {

              cin >> n >> k;

              maxrow = 0; //the max row number;

              maxcol = 0; //the max column number;

              for(i = 0; i < N; i++)

                     memset(wall[i], 0, sizeof(int)*N);

              for(i = 0; i < n; i++)

              {

                     cin >> col[0] >> row >> col[1] >> row;

                     if(col[0] > col[1])

                     {

                            itemp  = col[0];

                            col[0] = col[1];

                            col[1] = itemp;

                     }                  

                     for(j = col[0]; j <= col[1]; j++)

                            wall[row][j] = i+1;

                     if(maxrow < row)    maxrow = row;

                     if(maxcol < col[1]) maxcol = col[1];

              }

 

              res = 0;

              for(i = 0; i <= maxcol; i++)

              {

                     icolwall = 0;

                     for(j = 0; j <= maxrow; j++)

                     {

                            if(wall[j][i] != 0)

                                   icolwall++ ;

                     }

 

                     if(icolwall > k)

                     {

                            res += icolwall - k;

                            memset(cn, 0, sizeof(int)*N);

                            for(j = 0; j <= maxrow; j++)

                            {

                                   if(wall[j][i] != 0)

                                   {

                                          ic = i;

                                          while(wall[j][ic++] == wall[j][i])

                                                 cn[j]++ ;

                                   }

                            }

                     }

                     while(icolwall > k)

                     {

                            imax = 0;

                            ic = 0;

                            for(j = 0; j <= maxrow; j++)

                            {

                                   if(imax < cn[j])

                                   {

                                          imax = cn[j];

                                          ic = j;

                                   }

                            }

                            cn[ic] = 0;

                            j = i;

                            itemp = wall[ic][i];

                            while(wall[ic][j] == itemp)

                                   wall[ic][j++] = 0;

 

                            icolwall-- ;

                     }

              }

 

              cout << res << endl;            

              t-- ;

       }

 

       return 0;

}

提交结果:

Problem: 1230

 

User: uestcshe

Memory: 280K

 

Time: 0MS

Language: C++

 

Result: Accepted

 

你可能感兴趣的:(acm)