圆覆盖矩形问题

dourokinga 2009-09-12 03:15:32
求用最少个半径为r(r>0)的圆覆盖长为L,宽为D(L>D>0);


覆盖指的是不留空隙地用有限个圆盖住矩形
最后所有圆覆盖的面积肯定是>=矩形的面积的
当然单个圆的面积可以比矩形的面积大.

编程实现,谢谢
...全文
6295 32 打赏 收藏 转发到动态 举报
写回复
用AI写文章
32 条回复
切换为时间正序
请发表友善的回复…
发表回复
tusidike3212009023 2011-06-25
  • 打赏
  • 举报
回复
good!

好问题!!!!!!!!!!!!!!!!
tomorrowi 2010-11-13
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 linren2 的回复:]
上面的程序超出了行的长度了……

重新帖一下:
【程序】

C/C++ code
#include <windows.h>
#include <math.h>
#include <stdio.h>

#define WINDOW_WIDTH 400
#define WINDOW_HEIGHT 400
char* g_szApplicationName="圆覆盖矩形(矩形覆……
[/Quote]
我需要六边形的,求你解决好吗????我的QQ674089265在线等。也可以发到我邮箱。
FancyMouse 2010-01-09
  • 打赏
  • 举报
回复
>如果用六边形给出了答案,那么圆的个数就确定了,所以,我认为这同样是一个np-hard问题.
乃规约方向反了。。。刚才人家只说可以用六边形做圆,但是要证它nph是要用圆做六边形才能证
「已注销」 2010-01-09
  • 打赏
  • 举报
回复
首先说句不好意思先,现在才来结贴
其实这道题是我参加09年数模比赛时遇到的难点.三天的比赛过后就把它扔到一边了.哈~
想不到今天看到这么多厉害的讨论.实际上最后我也没给出最优解.只是讨论一下以正n边形代替覆盖的一些情况.
总之谢谢各位.
wangkefengyu 2009-10-28
  • 打赏
  • 举报
回复
很复杂的问题,从来没有想过这么多,受教了。。
wightmight 2009-10-27
  • 打赏
  • 举报
回复
厉害 厉害
佩服各位
latitude 2009-10-07
  • 打赏
  • 举报
回复
已经证明了:用最少的多边形覆盖多边形是一个NP-hard问题,那么,用六边形来覆盖矩形也是一个np-hard问题,如果用六边形给出了答案,那么圆的个数就确定了,所以,我认为这同样是一个np-hard问题.
chj_2003 2009-10-03
  • 打赏
  • 举报
回复
我们可否换个思路?
圆的面积给定,矩形给定。我们先不求需要多少个最少园。而是让每个圆尽可能大的为覆盖矩形作出贡献,这样自然需要的圆最少!
思考中
metears 2009-10-03
  • 打赏
  • 举报
回复
路过 好好学习
twilightgod 2009-09-29
  • 打赏
  • 举报
回复
二分枚举答案+暴力验证
linren2 2009-09-24
  • 打赏
  • 举报
回复
上面的程序超出了行的长度了……

重新帖一下:
【程序】
#include <windows.h>
#include <math.h>
#include <stdio.h>

#define WINDOW_WIDTH 400
#define WINDOW_HEIGHT 400
char* g_szApplicationName="圆覆盖矩形(矩形覆盖)";
char* g_szWindowClassName="LinrenWindowClass";

struct mypoint{
double x,y;
}myp[200];

struct myrect{
double x,y;
double x2,y2;
double x3,y3;
}myr[200];

/**只用修改这里******************************/
#define PARM_R 24.1
#define PARM_L 233.5
#define PARM_D 197.4
/******************************只用修改这里**/

int n,n2;
double r=PARM_R,l=PARM_L,d=PARM_D;
double at,sq2,x,y;
double a,e;
#undef PARM_R
#undef PARM_L
#undef PARM_D
char str[100];

void fun(){
int cl,cd,i,j;

x=(double(WINDOW_WIDTH)-l)/2.0;
y=(double(WINDOW_HEIGHT)-d)/2.0;

sq2=sqrt(2.0);
a=sq2*r;

at=(a-r)/sq2;

cl=(int)(l/a);
cd=(int)(d/a);
n=0;
for(i=0;i<cl;i++){
for(j=0;j<cd;j++){
myp[n].x=x+a*i;
myp[n].y=y+a*j;
n++;
}
}
e=(int)(r+r+1e-15);

n2=0;
double t1,t2,t3,t4;
int kd;
t1=l-cl*a;
t2=sqrt((r+r)*(r+r)-t1*t1);
t3=d-cd*a;
t4=sqrt((r+r)*(r+r)-t3*t3);

if(t1<t4){
kd=(int)(l/t4);
myr[n2].x=x+kd*t4;
myr[n2].y=y+cd*a;
myr[n2].x2=x+(kd+1)*t4;
myr[n2].y2=y+d;
myr[n2].x3=myr[n2].x-(r-t4/2.0);
myr[n2].y3=myr[n2].y-(r-t3/2.0);
n2++;
}else if(t3<t2){
kd=(int)(d/t2);
myr[n2].x=x+cl*a;
myr[n2].y=y+kd*t2;
myr[n2].x2=x+l;
myr[n2].y2=y+(kd+1)*t2;
myr[n2].x3=myr[n2].x-(r-t1/2.0);
myr[n2].y3=myr[n2].y-(r-t2/2.0);
n2++;
}else{
kd=(int)(l/t4);
myr[n2].x=x+kd*t4;
myr[n2].y=y+cd*a;
myr[n2].x2=x+(kd+1)*t4;
myr[n2].y2=y+d;
myr[n2].x3=myr[n2].x-(r-t4/2.0);
myr[n2].y3=myr[n2].y-(r-t3/2.0);
n2++;
kd=(int)(d/t2);
myr[n2].x=x+cl*a;
myr[n2].y=y+kd*t2;
myr[n2].x2=x+l;
myr[n2].y2=y+(kd+1)*t2;
myr[n2].x3=myr[n2].x-(r-t1/2.0);
myr[n2].y3=myr[n2].y-(r-t2/2.0);
n2++;
}

kd=(int)(d/t2);
for(i=0;i<kd;i++){
myr[n2].x=x+cl*a;
myr[n2].y=y+i*t2;
myr[n2].x2=x+l;
myr[n2].y2=y+(i+1)*t2;
myr[n2].x3=myr[n2].x-(r-t1/2.0);
myr[n2].y3=myr[n2].y-(r-t2/2.0);
n2++;
}

kd=(int)(l/t4);
for(i=0;i<kd;i++){
myr[n2].x=x+i*t4;
myr[n2].y=y+cd*a;
myr[n2].x2=x+(i+1)*t4;
myr[n2].y2=y+d;
myr[n2].x3=myr[n2].x-(r-t4/2.0);
myr[n2].y3=myr[n2].y-(r-t3/2.0);
n2++;
}
sprintf(str,"总数:%d",n+n2);
}

LRESULT CALLBACK WindowProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam){
static HBRUSH hbrush=(HBRUSH)GetStockObject(NULL_BRUSH);
static HPEN newpen=CreatePen(PS_SOLID,1,RGB(255,0,0));
static HPEN oldpen=NULL;
switch(msg){
case WM_CREATE:
{
PAINTSTRUCT ps;
int i;
BeginPaint(hwnd,&ps);
SelectObject(ps.hdc,hbrush);
for(i=0;i<n;i++){
Ellipse(ps.hdc,(int)(myp[i].x-at+0.5),(int)(myp[i].y-at+0.5),
(int)(myp[i].x-at+e+0.5),(int)(myp[i].y-at+e+0.5));
Rectangle(ps.hdc,(int)(myp[i].x+0.5),(int)(myp[i].y+0.5),
(int)(myp[i].x+a+0.5),(int)(myp[i].y+a+0.5));
}
for(i=0;i<n2;i++){
Ellipse(ps.hdc,(int)(myr[i].x3+0.5),(int)(myr[i].y3+0.5),
(int)(myr[i].x3+e+0.5),(int)(myr[i].y3+e+0.5));
Rectangle(ps.hdc,(int)(myr[i].x+0.5),(int)(myr[i].y+0.5),
(int)(myr[i].x2+0.5),(int)(myr[i].y2+0.5));
}
oldpen=(HPEN)SelectObject(ps.hdc,newpen);
Rectangle(ps.hdc,(int)(x+0.5),(int)(y+0.5),(int)(x+l+0.5),(int)(y+d+0.5));
SelectObject(ps.hdc,oldpen);
TextOut(ps.hdc,20,20,str,strlen(str));
EndPaint(hwnd,&ps);
}
break;

case WM_PAINT:
{
PAINTSTRUCT ps;
int i;
BeginPaint(hwnd,&ps);
SelectObject(ps.hdc,hbrush);
for(i=0;i<n;i++){
Ellipse(ps.hdc,(int)(myp[i].x-at+0.5),(int)(myp[i].y-at+0.5),
(int)(myp[i].x-at+e+0.5),(int)(myp[i].y-at+e+0.5));
Rectangle(ps.hdc,(int)(myp[i].x+0.5),(int)(myp[i].y+0.5),
(int)(myp[i].x+a+0.5),(int)(myp[i].y+a+0.5));
}
for(i=0;i<n2;i++){
Ellipse(ps.hdc,(int)(myr[i].x3+0.5),(int)(myr[i].y3+0.5),
(int)(myr[i].x3+e+0.5),(int)(myr[i].y3+e+0.5));
Rectangle(ps.hdc,(int)(myr[i].x+0.5),(int)(myr[i].y+0.5),
(int)(myr[i].x2+0.5),(int)(myr[i].y2+0.5));
}
oldpen=(HPEN)SelectObject(ps.hdc,newpen);
Rectangle(ps.hdc,(int)(x+0.5),(int)(y+0.5),(int)(x+l+0.5),(int)(y+d+0.5));
SelectObject(ps.hdc,oldpen);
TextOut(ps.hdc,20,20,str,strlen(str));
EndPaint(hwnd,&ps);
}
break;

case WM_DESTROY:
DeleteObject(hbrush);DeleteObject(newpen);DeleteObject(oldpen);
PostQuitMessage(0);break;
}
return DefWindowProc(hwnd,msg,wParam,lParam);
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
LPSTR szCmdLine,int iCmdShow){
HWND hWnd;
WNDCLASSEX winclass;
winclass.cbSize = sizeof(WNDCLASSEX);
winclass.style = CS_HREDRAW | CS_VREDRAW;
winclass.lpfnWndProc = WindowProc;
winclass.cbClsExtra = 0;
winclass.cbWndExtra = 0;
winclass.hInstance = hInstance;
winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
winclass.hbrBackground = (HBRUSH)GetStockObject (WHITE_BRUSH);
winclass.lpszMenuName = NULL;
winclass.lpszClassName = g_szWindowClassName;
winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

if (!RegisterClassEx(&winclass)){
MessageBox(NULL,"RegisterClassEx Error!","error",0);return 0;
}

hWnd=CreateWindowEx(NULL,
g_szWindowClassName,
g_szApplicationName,
WS_OVERLAPPEDWINDOW,
GetSystemMetrics(SM_CXSCREEN)/2-WINDOW_WIDTH/2,
GetSystemMetrics(SM_CYSCREEN)/2-WINDOW_HEIGHT/2,
WINDOW_WIDTH,
WINDOW_HEIGHT,
NULL,NULL,hInstance,NULL);

if(!hWnd){
MessageBox(NULL,"CreateWindowEx Error!","error",0);return 0;
}

fun();
ShowWindow(hWnd, iCmdShow);UpdateWindow(hWnd);

MSG msg;
while(GetMessage(&msg,NULL,0,0)){
TranslateMessage(&msg);DispatchMessage(&msg);
}
return msg.wParam;
}

【说明】
这个程序用来求解使用圆的内接矩形来覆盖目标矩形(红色部分)的最优解……
暂时还没有把六边形的情况添加进来……
linren 2009-09-24
  • 打赏
  • 举报
回复
【程序】
#include <windows.h>
#include <math.h>
#include <stdio.h>

#define WINDOW_WIDTH 400
#define WINDOW_HEIGHT 400
char* g_szApplicationName="圆覆盖矩形(矩形覆盖)";
char* g_szWindowClassName="LinrenWindowClass";

struct mypoint{
double x,y;
}myp[200];

struct myrect{
double x,y;
double x2,y2;
double x3,y3;
}myr[200];

/**只用修改这里******************************/
#define PARM_R 24.1
#define PARM_L 233.5
#define PARM_D 197.4
/******************************只用修改这里**/

int n,n2;
double r=PARM_R,l=PARM_L,d=PARM_D;
double at,sq2,x,y;
double a,e;
#undef PARM_R
#undef PARM_L
#undef PARM_D
char str[100];

void fun(){
int cl,cd,i,j;

x=(double(WINDOW_WIDTH)-l)/2.0;
y=(double(WINDOW_HEIGHT)-d)/2.0;

sq2=sqrt(2.0);
a=sq2*r;

at=(a-r)/sq2;

cl=(int)(l/a);
cd=(int)(d/a);
n=0;
for(i=0;i<cl;i++){
for(j=0;j<cd;j++){
myp[n].x=x+a*i;
myp[n].y=y+a*j;
n++;
}
}
e=(int)(r+r+1e-15);

n2=0;
double t1,t2,t3,t4;
int kd;
t1=l-cl*a;
t2=sqrt((r+r)*(r+r)-t1*t1);
t3=d-cd*a;
t4=sqrt((r+r)*(r+r)-t3*t3);

if(t1<t4){
kd=(int)(l/t4);
myr[n2].x=x+kd*t4;
myr[n2].y=y+cd*a;
myr[n2].x2=x+(kd+1)*t4;
myr[n2].y2=y+d;
myr[n2].x3=myr[n2].x-(r-t4/2.0);
myr[n2].y3=myr[n2].y-(r-t3/2.0);
n2++;
}else if(t3<t2){
kd=(int)(d/t2);
myr[n2].x=x+cl*a;
myr[n2].y=y+kd*t2;
myr[n2].x2=x+l;
myr[n2].y2=y+(kd+1)*t2;
myr[n2].x3=myr[n2].x-(r-t1/2.0);
myr[n2].y3=myr[n2].y-(r-t2/2.0);
n2++;
}else{
kd=(int)(l/t4);
myr[n2].x=x+kd*t4;
myr[n2].y=y+cd*a;
myr[n2].x2=x+(kd+1)*t4;
myr[n2].y2=y+d;
myr[n2].x3=myr[n2].x-(r-t4/2.0);
myr[n2].y3=myr[n2].y-(r-t3/2.0);
n2++;
kd=(int)(d/t2);
myr[n2].x=x+cl*a;
myr[n2].y=y+kd*t2;
myr[n2].x2=x+l;
myr[n2].y2=y+(kd+1)*t2;
myr[n2].x3=myr[n2].x-(r-t1/2.0);
myr[n2].y3=myr[n2].y-(r-t2/2.0);
n2++;
}

kd=(int)(d/t2);
for(i=0;i<kd;i++){
myr[n2].x=x+cl*a;
myr[n2].y=y+i*t2;
myr[n2].x2=x+l;
myr[n2].y2=y+(i+1)*t2;
myr[n2].x3=myr[n2].x-(r-t1/2.0);
myr[n2].y3=myr[n2].y-(r-t2/2.0);
n2++;
}

kd=(int)(l/t4);
for(i=0;i<kd;i++){
myr[n2].x=x+i*t4;
myr[n2].y=y+cd*a;
myr[n2].x2=x+(i+1)*t4;
myr[n2].y2=y+d;
myr[n2].x3=myr[n2].x-(r-t4/2.0);
myr[n2].y3=myr[n2].y-(r-t3/2.0);
n2++;
}
sprintf(str,"总数:%d",n+n2);
}

LRESULT CALLBACK WindowProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam){
static HBRUSH hbrush=(HBRUSH)GetStockObject(NULL_BRUSH);
static HPEN newpen=CreatePen(PS_SOLID,1,RGB(255,0,0));
static HPEN oldpen=NULL;
switch(msg){
case WM_CREATE:
{
PAINTSTRUCT ps;
int i;
BeginPaint(hwnd,&ps);
SelectObject(ps.hdc,hbrush);
for(i=0;i<n;i++){
Ellipse(ps.hdc,(int)(myp[i].x-at+0.5),(int)(myp[i].y-at+0.5),(int)(myp[i].x-at+e+0.5),(int)(myp[i].y-at+e+0.5));
Rectangle(ps.hdc,(int)(myp[i].x+0.5),(int)(myp[i].y+0.5),(int)(myp[i].x+a+0.5),(int)(myp[i].y+a+0.5));
}
for(i=0;i<n2;i++){
Ellipse(ps.hdc,(int)(myr[i].x3+0.5),(int)(myr[i].y3+0.5),(int)(myr[i].x3+e+0.5),(int)(myr[i].y3+e+0.5));
Rectangle(ps.hdc,(int)(myr[i].x+0.5),(int)(myr[i].y+0.5),(int)(myr[i].x2+0.5),(int)(myr[i].y2+0.5));
}
oldpen=(HPEN)SelectObject(ps.hdc,newpen);
Rectangle(ps.hdc,(int)(x+0.5),(int)(y+0.5),(int)(x+l+0.5),(int)(y+d+0.5));
SelectObject(ps.hdc,oldpen);
TextOut(ps.hdc,20,20,str,strlen(str));
EndPaint(hwnd,&ps);
}
break;

case WM_PAINT:
{
PAINTSTRUCT ps;
int i;
BeginPaint(hwnd,&ps);
SelectObject(ps.hdc,hbrush);
for(i=0;i<n;i++){
Ellipse(ps.hdc,(int)(myp[i].x-at+0.5),(int)(myp[i].y-at+0.5),(int)(myp[i].x-at+e+0.5),(int)(myp[i].y-at+e+0.5));
Rectangle(ps.hdc,(int)(myp[i].x+0.5),(int)(myp[i].y+0.5),(int)(myp[i].x+a+0.5),(int)(myp[i].y+a+0.5));
}
for(i=0;i<n2;i++){
Ellipse(ps.hdc,(int)(myr[i].x3+0.5),(int)(myr[i].y3+0.5),(int)(myr[i].x3+e+0.5),(int)(myr[i].y3+e+0.5));
Rectangle(ps.hdc,(int)(myr[i].x+0.5),(int)(myr[i].y+0.5),(int)(myr[i].x2+0.5),(int)(myr[i].y2+0.5));
}
oldpen=(HPEN)SelectObject(ps.hdc,newpen);
Rectangle(ps.hdc,(int)(x+0.5),(int)(y+0.5),(int)(x+l+0.5),(int)(y+d+0.5));
SelectObject(ps.hdc,oldpen);
TextOut(ps.hdc,20,20,str,strlen(str));
EndPaint(hwnd,&ps);
}
break;

case WM_DESTROY:
DeleteObject(hbrush);DeleteObject(newpen);DeleteObject(oldpen);
PostQuitMessage(0);break;
}
return DefWindowProc(hwnd,msg,wParam,lParam);
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
LPSTR szCmdLine,int iCmdShow){
HWND hWnd;
WNDCLASSEX winclass;
winclass.cbSize = sizeof(WNDCLASSEX);
winclass.style = CS_HREDRAW | CS_VREDRAW;
winclass.lpfnWndProc = WindowProc;
winclass.cbClsExtra = 0;
winclass.cbWndExtra = 0;
winclass.hInstance = hInstance;
winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
winclass.hbrBackground = (HBRUSH)GetStockObject (WHITE_BRUSH);
winclass.lpszMenuName = NULL;
winclass.lpszClassName = g_szWindowClassName;
winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

if (!RegisterClassEx(&winclass)){
MessageBox(NULL,"RegisterClassEx Error!","error",0);return 0;
}

hWnd=CreateWindowEx(NULL,
g_szWindowClassName,
g_szApplicationName,
WS_OVERLAPPEDWINDOW,
GetSystemMetrics(SM_CXSCREEN)/2-WINDOW_WIDTH/2,
GetSystemMetrics(SM_CYSCREEN)/2-WINDOW_HEIGHT/2,
WINDOW_WIDTH,
WINDOW_HEIGHT,
NULL,NULL,hInstance,NULL);

if(!hWnd){
MessageBox(NULL,"CreateWindowEx Error!","error",0);return 0;
}

fun();
ShowWindow(hWnd, iCmdShow);UpdateWindow(hWnd);

MSG msg;
while(GetMessage(&msg,NULL,0,0)){
TranslateMessage(&msg);DispatchMessage(&msg);
}
return msg.wParam;
}

【运行结果】
linren 2009-09-23
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 lhylhy 的回复:]
对于比较大的矩形可以用内接六边形。
[/Quote]六边形的想法非常好
lhy 2009-09-23
  • 打赏
  • 举报
回复
对于比较大的矩形可以用内接六边形。
linren 2009-09-23
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 linren 的回复:]
就是把15、16楼中使用的六边形旋转60度使用……
[/Quote]
打错了……
应该是90度……
linren 2009-09-23
  • 打赏
  • 举报
回复
六边形的覆盖除了15、16楼中最上面不是的顶点的覆盖方法
还有一种最上面为的顶点的覆盖方法

就是把15、16楼中使用的六边形旋转60度使用……

[Quote=引用 17 楼 lhylhy 的回复:]
如果矩形的长宽都远大于圆的直径,用六边形可以节省23%的圆。

这个问题很复杂,我估计除非是数学家,不然很难解决。
或者考虑一下穷举法。

[/Quote]
确实是非常复杂的题目……
lhy 2009-09-23
  • 打赏
  • 举报
回复
如果矩形的长宽都远大于圆的直径,用六边形可以节省23%的圆。

这个问题很复杂,我估计除非是数学家,不然很难解决。
或者考虑一下穷举法。
linren 2009-09-23
  • 打赏
  • 举报
回复

上面是对另一种情况的覆盖
正方形覆盖需要4个……
六边形覆盖需要7个……
linren 2009-09-23
  • 打赏
  • 举报
回复

上图中用六边形覆盖需要22个……
用矩形覆盖的话需要3种矩形,共计25个……
贝隆 2009-09-22
  • 打赏
  • 举报
回复
受教
加载更多回复(11)

33,025

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧