题意:
给一些平行于x轴的墙,求最少去掉多少墙使得x轴上每点穿过不超过k面墙。
分析:
一开始还以为是重复覆盖问题(取最少的行使每列至少一个1),其实这题是可以用贪心解的(类似取最多的行使每列至多k个1)。
代码:
//poj 1230 //sep9 #include <iostream> using namespace std; const int maxN=128; int n,max_k,maxx,maxy; int g[maxN][maxN]; int work() { int ans=0; for(int j=0;j<=maxx;++j){ int sum=0; for(int i=0;i<=maxy;++i) sum+=(g[i][j]>0?1:0); while(sum>max_k){ int index,t_sum=-1; for(int k=0;k<=maxy;++k){ int r_sum=0; if(g[k][j]==0) continue; for(int x=j;x<=maxx&&g[k][x]==g[k][j];++x) ++r_sum; if(r_sum>t_sum){ t_sum=r_sum; index=k; } } ++ans; for(int x=j,tmp=g[index][j];x<=maxx&&g[index][x]==tmp;++x) g[index][x]=0; --sum; } } return ans; } int main() { int cases; scanf("%d",&cases); while(cases--){ scanf("%d%d",&n,&max_k); memset(g,0,sizeof(g)); maxx=-1,maxy=-1; for(int t=1;t<=n;++t){ int x1,x2,y; scanf("%d%d%d%d",&x1,&y,&x2,&y); if(x2<x1) swap(x1,x2); maxx=max(maxx,x2); maxy=max(maxy,y); for(int i=x1;i<=x2;++i) g[y][i]=t; } printf("%d\n",work()); } return 0; }
时间: 2024-10-13 14:52:46