POJ 1230(贪心)


/**POJ 1230 
   题意:魔术师穿墙,由于体力有限,最多可以穿越max个墙。要求尽可能去掉几个墙,让魔术师在每一列都可以表演顺利;
   思路:贪心,按照墙的左端点从小到大排序后,从左往右开始寻找多余方格所在最长墙,尽可能的删除一个墙,去掉更多的方格
   细节:墙可以是连续的,但不重叠 
*/ 
#include <algorithm>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<iostream>
using namespace std;
template <class T> void swap ( T& a, T& b )  
{  
  T c(a); a=b; b=c;  
}  
struct grid
{
       int bx,by,ex,ey;
}GridW;
int cmp(const void *a, const void *b)
{
    return (*(grid *)a).by > (*(grid *)b).by ? 1:-1;
}
grid g[102];
int main()
{
    int t,n,max,i,j,k,re;
    cin >> t ;
    while(t--)
    {
             int wall[102]={0},mmax=-1;//mmax 为最右一列墙的列数   wall数组记录每列墙的个数 
              cin >> n >> max;
              for (re=i=0; i<n; i++)
              {

                      cin >> g[i].by >> g[i].bx >> g[i].ey >> g[i].ex;
                      if(g[i].by>g[i].ey) 
						  ::swap(g[i].by,g[i].ey);//前后端点无序,判断排序 
		               if(mmax < g[i].ey) mmax = g[i].ey;
                      for (j=g[i].by; j<=g[i].ey; j++)wall[j]++;//wall 统计各列墙的数目 
              }
              qsort(g,n,sizeof(g[0]),cmp);//按照左端点Y值从小到大排序             
              for (re=i=0; i<=mmax; i++)
              while(wall[i] > max)
              {
                        int Max=-1,posi;    //Max 记录可以消除当前方格所在墙的最右端列数,以便比较找到最长的墙 posi记录最长墙的下标 
                        for (j=0; j<n; j++)//寻找方格所在最长的墙 
                        {
                            if(g[j].by <= i && g[j].ey>= i && g[j].ey >Max)
                              Max = g[j].ey,posi=j;
                            if(g[j].by > i) break;    
                        }
                        for (j=g[posi].by; j<=g[posi].ey; j++)//更新最长墙上的方格 
                        wall[j]--;
                        re++;g[posi].by=g[posi].ey=0;  //删除墙                
              }
              cout << re << endl;
    }
    return 0;
} 


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值