挺简单的算法我没想出来..
考虑最左边的需要移除墙的列。这列是必定要移除一些墙的。
不妨移除右边界较大的那些墙。
实现的时候,可以用基数排序的方式来找到右边界较大的墙。
开两个数组如下:
map[i][j] = { 第i列中,从该列开始向右延伸,长度为j的墙的数目}
cnt[i] = {第i列中墙的数目}
这样代码比较方便,速度也快。 ——荣誉属于糯米
糯米的这个数据结构非常棒, 我做了一点改进: 糯米记录了右边还有多长的墙, 实际上只要记录右边墙的边界就可以了, 省掉一些计算和思维复杂度
所以我的代码精简一点, 看我的吧 🙂
这种题一眼看上去像DP, 我看了点东西说DP和贪心有很多相似之处, 比如都是找最优子结构. 区别在于贪心从最优子结构里选出一个或几个就行. 具体有什么区别也没太搞清楚, 感觉DP有一个图的延伸, 每个状态都可能被多次使用, 而贪心不会.
代码点下面:
#include <stdio.h> #include <string.h> int main () { int t; scanf("%d",&t); while(t--) { int N,K; scanf("%d%d",&N,&K); int a[101][101],k[101]; memset(a,0x00,sizeof(a)); memset(k,0x00,sizeof(k)); for(int i=1;i<=N;i++) { int x0,y,x1; scanf("%d%d%d%d",&x0,&y,&x1,&y); if(x0>x1) { x0^=x1; x1^=x0; x0^=x1; } for(int foo=x0;foo<=x1;foo++) { a[foo][x1]++; k[foo]++; } } int result=0; for(int i=0;i<=100;i++) while(k[i]>K) { int w; //right edge of wall for(w=100;a[i][w]==0;w--); for(int j=i;j<=w;j++) { a[j][w]--; k[j]--; } result++; } printf("%d\n",result); } return 0; }