一直在想如何打植物大战僵尸,题目题意都没有好好理解。晚上静下心来才明白白天都想错了。实际上下午用了修改器发现pvz好无聊。
这是算法竞赛入门经典p233页中的区域覆盖问题,书本上讲的看了好久才懂,主要是我以为就只能用一条,实际上题意是用最少的条数组合起来。
写法就是排序和扫描,排序按左端点从小到大排。输入时先将右端点小于0的数据去掉,根本不可能用到。再进行一次预处理,找出第一段,要求左端点值小于等于0,右端点y1值最大。如果右端点y1已经大于m,可以结束了。否则进行下一轮选择,这次找的是左端点小于等于y1且右端点最大,再进行和上面一样的判断,直到找到答案或者发现无解。
#include<stdio.h> #include<algorithm> using namespace std; const int N=100003; struct da { int x,y; }a[N],b[N]; bool cmp(da a,da b)//结构体排序 { return a.x<b.x; } int main() { int cas,i,n,m,j,cnt,s,e,pos,mix,temp,f; scanf("%d",&cas); while(cas--) { n=0; scanf("%d",&m); while(scanf("%d %d",&s,&e)) { if(s==0&&e==0) break; if(e>=0){a[n].x=s;a[n].y=e;++n;}//处理输入数据 } sort(a,a+n,cmp);//排序 if(a[0].x>0) printf("0\n");//第一个区间起点就大于0,无解 else { mix=cnt=pos=0;//cnt计数,mix选用点的序号 for(pos=0;pos<n&&a[pos].x<=0;pos++) if(a[pos].y>a[mix].y) mix=pos; pos=mix;b[0].x=a[mix].x;b[0].y=a[mix].y;//第一段 while(pos<n&&b[cnt].y<m)//判断是否一段可以完成 { f=1;//标记有没有找到下一段 temp=mix;//临时记录 while(pos+1<n&&a[pos+1].x<=a[mix].y) { f=0; pos++; if(a[pos].y>a[temp].y) temp=pos; } if(f) break;//没有找到答案结束寻找 mix=temp; cnt++;b[cnt].x=a[mix].x;b[cnt].y=a[mix].y; } if(b[cnt].y>=m)//最右端大于m,有解 { printf("%d\n",cnt+1); for(i=0;i<=cnt;i++)printf("%d %d\n",b[i].x,b[i].y); } else printf("0\n"); } if(cas) printf("\n"); } return 0; }