解题思路:这道题目是用贪心的思想,从左向右扫描场地的每一列是否合法。若不合法,贪心的找出从该列起向右延伸最长的m道墙,移除这m道墙使得该列合法。
我最开始代码会出现这样的问题:如果两个墙是连在一起的,那么会被当做一个墙来处理。。。
AC:
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int White = 0;
int n, k;
int w, h;
short g[101][101];
int Greedy()
{
int minCount = 0;
for( int c = 0; c <= w; ++ c )
{
// 扫描每一行,找出墙数num
int num = 0;
for( int r = 0; r <= h; ++ r )
if( g[r][c] != White )
++ num;
// 移除多余墙
while( num > k )
{
// 找出所有墙中右端点最大的索引
int ind = -1, maxCount = 0;
for(int r = 0; r <= h; ++r)
if( g[r][c] != White )
{
int cc = c + 1, count = 0;
while( g[r][cc++] == g[r][c] ) ++ count;
if( count > maxCount )
{
maxCount = count;
ind = r;
}
}
for( int cc = c; cc <= c + maxCount; ++ cc ) g[ind][cc] = White;
-- num;
++ minCount;
}
}
return minCount;
}
int main()
{
int T;
scanf("%d",&T);
while( T -- )
{
memset( g, White, sizeof(g) );
scanf( "%d%d", & n, & k );
for( int i = 0; i < n; ++ i )
{
int bx, by, ex, ey;
scanf( "%d%d%d%d", & bx, & by, & ex, & ey );
if( bx > ex ) ::swap( bx, ex );
if( ex > w ) w = ex;
if( ey > h ) h = ey;
for( int c = bx; c <= ex; ++ c )
g[by][c] = i + 1;
}
printf("%d\n",Greedy());
}
return 0;
}