矩形覆盖题解.doc_第1页
矩形覆盖题解.doc_第2页
矩形覆盖题解.doc_第3页
矩形覆盖题解.doc_第4页
矩形覆盖题解.doc_第5页
已阅读5页,还剩23页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第四题矩形覆盖矩形覆盖(存盘名NOIPG4)问题描述:在平面上有 n 个点(n = 50),每个点用一对整数坐标表示。例如:当 n4 时,4个点的坐标分另为:p1(1,1),p2(2,2),p3(3,6),P4(0,7),见图一。这些点可以用 k 个矩形(1=k=4)全部覆盖,矩形的边平行于坐标轴。当 k=2 时,可用如图二的两个矩形 sl,s2 覆盖,s1,s2 面积和为 4。问题是当 n 个点坐标和 k 给出后,怎样才能使得覆盖所有点的 k 个矩形的面积之和为最小呢。约定:覆盖一个点的矩形面积为 0;覆盖平行于坐标轴直线上点的矩形面积也为0。各个矩形必须完全分开(边线与顶点也都不能重合)。 输入:键盘输人文件名。文件格式为n kxl y1x2 y2. .xn yn (0=xi,yi=500) 输出:输出至屏幕。格式为:一个整数,即满足条件的最小的矩形面积之和。 输入输出样例d.in :4 21 12 23 60 7屏幕显示:4分析【题解一】1、本题的难度较大。如果你这样认为:即在假定已用i个矩形(面积和满足最小)覆盖所有点的基础上,穷举所有2个矩形合并成1个矩形(条件是:在所有合并方案中使合并后面积最小),从而使矩形个数减少为i-1那就错了,可是却可以通过前4组测试数据!正确的做法是对不同的K值分别进行计算,好在K值较小,否则.讨论:k=1,只要求出n个点坐标的最大、最小值,就可求得矩形的位置与面积;k=2,有2个矩形,它们只有2种分布形式:左右式(flag=0),上下式(flag=1)12flag=021flag=1对于左右式,显然要先将所有点按横坐标升序排列,可将点1点i-1放入矩形1中,将点i点n放入矩形2中,求两矩形的面积之和;如果面积和比上一个值小,记下;让i从2循环到n,就可完成左右式的全部搜索;对于上下式,先将所有点按纵坐标升序排列,依此类推。k=3,有3个矩形,它们有6种分布形式:123flag=1123flag=0321flag=2123flag=3123flag=4123flag=5要用两重循环进行搜索:设i,j为循环变量,将点1i-1放入矩形1中,点ij-1放入矩形2中,点jn放入矩形3中;点必须在放入前排好序(均为升序):对于flag=0,所有点按横坐标排序;对于flag=1,所有点按纵坐标排序;对于flag=2,所有点先按横坐标排序,然后点in按纵坐标排序;对于flag=3,所有点先按横坐标排序,然后点1j-1按纵坐标排序;对于flag=4,所有点先按纵坐标排序,然后点1j-1按横坐标排序;对于flag=5,所有点先按纵坐标排序,然后点in按横坐标排序;至于k=4,4个矩形有22种分布形式,实在太复杂!幸好测试数据中没有K=4的情形(似乎有意放了一马?)。据说本题全国没有一人全对!(只要求K=1,2,3)程序清单$A+,B-,D+,E+,F-,G-,I+,L+,N-,O-,P-,Q-,R-,S-,T-,V+,X+,Y+$M 65520,0,655360program NOIPG4; const maxn=50;maxk=3; type rect=record定义矩形数据类型 l,r,t,b:word;矩形的左边,右边,下边,上边距坐标轴的距离 end; vxy=record定义点数据类型 x,y:word;点的横、纵坐标 end; var ju:array1.maxkof rect; v:array1.maxn,0.2 of vxy;v0:vxy; n,k,i,j,ii,jj:byte;f:text;filename:string; Smin,temp:longint; function intersect(jui,juj:rect):boolean;判断两矩形是否有公共点 var b1,b2,t1,t2,l1,l2,r1,r2:word; begin b1:=jui.b;b2:=juj.b;t1:=jui.t;t2:=juj.t; l1:=jui.l;l2:=juj.l;r1:=jui.r;r2:=juj.r; intersect:=(l2=l1) or (r2=l1) or (l2=r1) and (t2=t1) or (b2=t1) or (b2=b1) and (t2=t1); end; function area(ju:rect):longint;求矩形的面积 var temp:longint; begintemp:=ju.b-ju.t;area:=temp*(ju.r-ju.l);不能直接写成area:=(ju.b-ju.t)*(ju.r-ju.l);因为这样可能会溢出! end; procedure insert(v:vxy;var ju:rect);将点放入矩形 begin if v.xju.r then ju.r:=v.x; if v.yju.b then ju.b:=v.y; end; procedure init;初始化 begin write(Input filename:);readln(filename); assign(f,filename);reset(f);readln(f,n,k); for i:=1 to n do begin read(f,vi,0.x,vi,0.y); vi,1.x:=vi,0.x;vi,1.y:=vi,0.y; end; for i:=1 to n-1 do按横坐标升序排列各点,存入vi,0 for j:=i+1 to n do if vi,0.xvj,0.x then begin v0:=vi,0;vi,0:=vj,0;vj,0:=v0; end; for i:=1 to n-1 do按纵坐标升序排列各点,存入vi,1 for j:=i+1 to n do if vi,1.yvj,1.y then begin v0:=vi,1;vi,1:=vj,1;vj,1:=v0; end; end; procedure solve;核心计算 begin smin:=maxlongint; case k of 1:beginK=1的情形 ju1.b:=vn,1.y;ju1.t:=v1,1.y; ju1.r:=vn,0.x;ju1.l:=v1,0.x; smin:=area(ju1); end; 2:for jj:=0 to 1 do beginK=2的情形 flag=0,1的情形 ju1.b:=v1,jj.y;ju1.t:=v1,jj.y; ju1.r:=v1,jj.x;ju1.l:=v1,jj.x; for i:=2 to n do begin insert(vi-1,jj,ju1);将第i-1点放入矩形1 ju2.b:=vi,jj.y;ju2.t:=vi,jj.y;将第i至n点放入矩形2 ju2.r:=vi,jj.x;ju2.l:=vi,jj.x; for ii:=i+1 to n do insert(vii,jj,ju2); if not intersect(ju1,ju2) then begin如果两矩形不交叉 temp:=0;for ii:=1 to k do temp:=temp+area(juii); if tempsmin then smin:=temp; end; end; end; 3:begin for jj:=0 to 1 do begin flag=0,1的情形 ju1.b:=v1,jj.y;ju1.t:=v1,jj.y; ju1.r:=v1,jj.x;ju1.l:=v1,jj.x; for i:=2 to n-1 do begin insert(vi-1,jj,ju1); ju2.b:=vi,jj.y;ju2.t:=vi,jj.y; ju2.r:=vi,jj.x;ju2.l:=vi,jj.x; if intersect(ju1,ju2) then continue; for j:=i+1 to n do begin insert(vj-1,jj,ju2); ju3.b:=vj,jj.y;ju3.t:=vj,jj.y; ju3.r:=vj,jj.x;ju3.l:=vj,jj.x; for ii:=j+1 to n do insert(vii,jj,ju3); if intersect(ju2,ju3) then continue; temp:=0;for ii:=1 to k do temp:=temp+area(juii); if tempvjj,2.y then begin v0:=vii,2;vii,2:=vjj,2;vjj,2:=v0; end;结果:所有点先按横坐标升序排列,然后点i至n按纵坐标升序排列 insert(vi-1,2,ju1);将第i-1点放入矩形1 ju2.b:=vi,2.y;ju2.t:=vi,2.y;将第i点放入矩形2 ju2.r:=vi,2.x;ju2.l:=vi,2.x; if intersect(ju1,ju2) then continue; for j:=i+1 to n do begin insert(vj-1,2,ju2);将第j-1点放入矩形2 ju3.b:=vj,2.y;ju3.t:=vj,2.y;将第j至n点放入矩形3 ju3.r:=vj,2.x;ju3.l:=vj,2.x; for ii:=j+1 to n do insert(vii,2,ju3); if intersect(ju2,ju3) then continue; temp:=0;for ii:=1 to k do temp:=temp+area(juii); if tempvjj,2.y then begin v0:=vii,2;vii,2:=vjj,2;vjj,2:=v0; end; ju3.b:=vj,2.y;ju3.t:=vj,2.y; ju3.r:=vj,2.x;ju3.l:=vj,2.x; for ii:=j+1 to n do insert(vii,2,ju3); for i:=2 to j-1 do begin ju2.b:=vi,2.y;ju2.t:=vi,2.y; ju2.r:=vi,2.x;ju2.l:=vi,2.x; for ii:=i+1 to j-1 do insert(vii,2,ju2); ju1.b:=v1,2.y;ju1.t:=v1,2.y; ju1.r:=v1,2.x;ju1.l:=v1,2.x; for ii:=2 to i-1 do insert(vii,2,ju1); if intersect(ju1,ju2) or intersect(ju2,ju3) or intersect(ju1,ju3) then continue; temp:=0;for ii:=1 to k do temp:=temp+area(juii); if tempvjj,2.x then begin v0:=vii,2;vii,2:=vjj,2;vjj,2:=v0; end; ju3.b:=vj,2.y;ju3.t:=vj,2.y; ju3.r:=vj,2.x;ju3.l:=vj,2.x; for ii:=j+1 to n do insert(vii,2,ju3); for i:=2 to j-1 do begin ju2.b:=vi,2.y;ju2.t:=vi,2.y; ju2.r:=vi,2.x;ju2.l:=vi,2.x; for ii:=i+1 to j-1 do insert(vii,2,ju2); ju1.b:=v1,2.y;ju1.t:=v1,2.y; ju1.r:=v1,2.x;ju1.l:=v1,2.x; for ii:=2 to i-1 do insert(vii,2,ju1); if intersect(ju1,ju2) or intersect(ju2,ju3) or intersect(ju1,ju3) then continue; temp:=0;for ii:=1 to k do temp:=temp+area(juii); if tempvjj,2.x then begin v0:=vii,2;vii,2:=vjj,2;vjj,2:=v0; end; insert(vi-1,2,ju1); ju2.b:=vi,2.y;ju2.t:=vi,2.y; ju2.r:=vi,2.x;ju2.l:=vi,2.x; if intersect(ju1,ju2) then continue; for j:=i+1 to n do begin insert(vj-1,2,ju2); ju3.b:=vj,2.y;ju3.t:=vj,2.y; ju3.r:=vj,2.x;ju3.l:=vj,2.x; for ii:=j+1 to n do insert(vii,2,ju3); if intersect(ju2,ju3) then continue; temp:=0;for ii:=1 to k do temp:=temp+area(juii); if tempsmin then smin:=temp; end; end; end; end; end; begin主程序 init; solve; writeln(smin); end.点评:压轴题 据说,本次复赛主要是前三题的竞争,可见本题能得分的人相当少,但是K=1应该说是送分的,K=2也是比较容易的。通过测试,发现在K=3的第4、5组测试数据中仅用到了flag=1的情形,也就是说,只要写出flag=1的程序段就OK了(没写flag=0,2,3,4,5的同学偷着乐?)。【题解二】具体方法是将每个点极角排序然后就是一个经典的DP了:fi,j,k=min(fi,j,k,fi,t,k-1+st+1,j)另外注意要DP两次因为可以是横着的也可以是竖着的具体实现参见以下代码:varn,m,i,t,ans,last:longint;x,y:array1.51 of integer;procedure sort(l,r:integer);vari,j,mid,t:integer;begini:=l;j:=r;mid:=x(l+r) shr 1;repeatwhile(ximid) do dec(j);if ij;if ir then sort(i,r);if lj then sort(l,j);end;procedure qsort(l,r:integer);vari,j,mid,t:integer;begini:=l;j:=r;mid:=y(l+r) shr 1;repeatwhile(yimid) do dec(j);if ij;if ir then qsort(i,r);if lsmax then smax:=yi;if yismin then smin:=yi;end;hight:=smax-smin;end;function min(x,y:longint):longint;beginif xy then min:=x else min:=y;end;procedure Dynamic;varj,k,p:integer;s:array1.50,1.50 of longint;f:array1.50,1.50,1.4 of longint;beginfor i:=1 to m dofor j:=1 to m dofor k:=1 to n dofi,j,k:=300000;for i:=1 to m dofor j:=i to m dobeginsi,j:=(xj-xi)*hight(i,j);fi,j,1:=si,j;end;for p:=1 to m dofor i:=1 to m-p dobeginj:=i+p;for k:=2 to n dofor t:=i to j-1 dofi,j,k:=min(fi,j,k,fi,t,k-1+st+1,j);end;ans:=min(ans,f1,m,n);end;beginassign(input,t4.in);reset(input);assign(output,t4.out);rewrite(output);readln(m,n);for i:=1 to m doreadln(xi,yi);xm+1:=maxint;ym+1:=maxint;ans:=maxlongint;sort(1,m);t:=x1;last:=1;for i:=2 to m+1 doif xit thenbeginqsort(last,i-1);t:=xi;last:=i;end;Dynamic;for i:=1 to m dobegint:=xi;xi:=yi;yi:=t;end;sort(1,m);t:=x1;last:=1;for i:=2 to m+1 doif xit thenbeginqsort(last,i-1);t:=xi;last:=i;end;Dynamic;writeln(ans);close(input);close(output);end.【题解三】 好吧,我承认,此题真正地震撼了我,我无语。 K明明是1到4的取值,由于数据最大K为3,然后所有的做法竟然都是分情况模拟!K=1时如何,K=2时有哪些分的情况。(上下分,左右分),K=3的时候6种情况。 每次都要排序X,Y坐标,算面积。$A+,B-,D+,E+,F-,G-,I+,L+,N-,O-,P-,Q-,R-,S-,T-,V+,X+,Y+$M 65520,0,655360program NOIPG4;const maxn=50;maxk=3;type rect=record定义矩形数据类型 l,r,t,b:word;矩形的左边,右边,下边,上边距坐标轴的距离 end; vxy=record定义点数据类型 x,y:word;点的横、纵坐标 end;var ju:array1.maxkof rect; v:array1.maxn,0.2 of vxy;v0:vxy; n,k,i,j,ii,jj:byte;f:text;filename:string; Smin,temp:longint;function intersect(jui,juj:rect):boolean;判断两矩形是否有公共点 var b1,b2,t1,t2,l1,l2,r1,r2:word; begin b1:=jui.b;b2:=juj.b;t1:=jui.t;t2:=juj.t; l1:=jui.l;l2:=juj.l;r1:=jui.r;r2:=juj.r; intersect:=(l2=l1) or (r2=l1) or (l2=r1) and (t2=t1) or (b2=t1) or (b2=b1) and (t2=t1); end;function area(ju:rect):longint;求矩形的面积 var temp:longint; begin temp:=ju.b-ju.t; area:=temp*(ju.r-ju.l); end;procedure insert(v:vxy;var ju:rect);将点放入矩形 begin if v.xju.r then ju.r:=v.x; if v.yju.b then ju.b:=v.y; end;procedure init;初始化 begin write(Input filename:);readln(filename); assign(f,filename);reset(f);readln(f,n,k); for i:=1 to n do begin read(f,vi,0.x,vi,0.y); vi,1.x:=vi,0.x;vi,1.y:=vi,0.y; end; for i:=1 to n-1 do按横坐标升序排列各点,存入vi,0 for j:=i+1 to n do if vi,0.xvj,0.x then begin v0:=vi,0;vi,0:=vj,0;vj,0:=v0; end; for i:=1 to n-1 do按纵坐标升序排列各点,存入vi,1 for j:=i+1 to n do if vi,1.yvj,1.y then begin v0:=vi,1;vi,1:=vj,1;vj,1:=v0; end; end;procedure solve;核心计算 begin smin:=maxlongint; case k of 1:beginK=1的情形 ju1.b:=vn,1.y;ju1.t:=v1,1.y; ju1.r:=vn,0.x;ju1.l:=v1,0.x; smin:=area(ju1); end; 2:for jj:=0 to 1 do beginK=2的情形 flag=0,1的情形 ju1.b:=v1,jj.y;ju1.t:=v1,jj.y; ju1.r:=v1,jj.x;ju1.l:=v1,jj.x; for i:=2 to n do begin insert(vi-1,jj,ju1);将第i-1点放入矩形1 ju2.b:=vi,jj.y;ju2.t:=vi,jj.y;将第i至n点放入矩形2 ju2.r:=vi,jj.x;ju2.l:=vi,jj.x; for ii:=i+1 to n do insert(vii,jj,ju2); if not intersect(ju1,ju2) then begin如果两矩形不交叉 temp:=0;for ii:=1 to k do temp:=temp+area(juii); if tempsmin then smin:=temp; end; end; end; 3:begin for jj:=0 to 1 do begin flag=0,1的情形 ju1.b:=v1,jj.y;ju1.t:=v1,jj.y; ju1.r:=v1,jj.x;ju1.l:=v1,jj.x; for i:=2 to n-1 do begin insert(vi-1,jj,ju1); ju2.b:=vi,jj.y;ju2.t:=vi,jj.y; ju2.r:=vi,jj.x;ju2.l:=vi,jj.x; if intersect(ju1,ju2) then continue; for j:=i+1 to n do begin insert(vj-1,jj,ju2); ju3.b:=vj,jj.y;ju3.t:=vj,jj.y; ju3.r:=vj,jj.x;ju3.l:=vj,jj.x; for ii:=j+1 to n do insert(vii,jj,ju3); if intersect(ju2,ju3) then continue; temp:=0;for ii:=1 to k do temp:=temp+area(juii); if tempvjj,2.y then begin v0:=vii,2;vii,2:=vjj,2;vjj,2:=v0; end;结果:所有点先按横坐标升序排列,然后点i至n按纵坐标升序排列 insert(vi-1,2,ju1);将第i-1点放入矩形1 ju2.b:=vi,2.y;ju2.t:=vi,2.y;将第i点放入矩形2 ju2.r:=vi,2.x;ju2.l:=vi,2.x; if intersect(ju1,ju2) then continue; for j:=i+1 to n do begin insert(vj-1,2,ju2);将第j-1点放入矩形2 ju3.b:=vj,2.y;ju3.t:=vj,2.y;将第j至n点放入矩形3 ju3.r:=vj,2.x;ju3.l:=vj,2.x; for ii:=j+1 to n do insert(vii,2,ju3); if intersect(ju2,ju3) then cont

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论