边长为n的正方形最多可以放下多少个半径为r的圆?

2023-11-03 11:40
文章标签 边长 正方形 半径 放下

本文主要是介绍边长为n的正方形最多可以放下多少个半径为r的圆?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

今天看见数院群里有人在讨论一道有意思的题目,题意好像是这样的:在一个10x10的正方形里最多可以放多少个半径为1圆?在知乎里找到了10*10的正方形能放多少个直径为1的圆,那么最优的放置方法如下:
在这里插入图片描述
从图中可以看出,并不是每一排放10个,放10排是最优的。因为这样会造成中间的空隙很大。可以看出可能更优的放置方法是:交错着放,即(图中从下往上看):第一排放10个,第二排放9个,第三排放10个。第二排的每一个都放在两个的中间,虽然这样第二排少放了一个,但是它给占用的高度更小了。如果一直这样放就有可能使得累计出来的高度多放一排。但是我们却不知道用减少个数来换取余留下来的高度是否是值得的。(比如下图所示:正方形边长是3,那么交错放,只能放3+2+3=8个,这样红线以下余留下来的高度不足以再放下一排)
在这里插入图片描述
为了简化问题,只讨论正方形边长能被圆直径整除的情况。
应该怎样决策呢?现在已经确定最优的放法就是每一排要么放满n个,要么和上一排交错放,放n-1个或者n个,因为这样能最少的占用高度。
如果不交错放,那么它占用的高度就是2r。如果交错放,用勾股定理算出占用的高度是√3r。如下图所示:
在这里插入图片描述这样很容易想到用动态规划来解决这个问题。因为它的决策阶段很明显被划分成了一排一排的,而每一排有2种决策方法。由于还要记录它决策过程中的高度。所以要用一维来方便计算出目前放置的高度。可以增加一个状态来表示交错放置了多少次。这样来定义状态:用f[i][j][k]来表示:前i行中,交错放置了j次,并且第i行的放置状态为k时,最多放置圆的个数。其中k只有两种取值,k=0时表示这一排放满s个,k=1时表示这一排放s-1个(其中s=n/2r)。判断是否是加错放只需要判断上一行的k和这一行的k是否不相等。同时呢,还需要计算它当前的高度,可以用g[i][j][k]来记录高度。

这样它们的这状态转移方程很容易写出来:
记每一排放满恰好能放s个。

f[i][j][0]=max(f[i-1][j-1][1],f[i-1][j][0])+s
g[i][j][0]=g[i-1][j-1][1]+√3r , 当f[i-1][j-1][0]<f[i-1][j][1]时
g[i][j][0]=g[i-1][j][0]+2r , 当f[i-1][j-1][0]>f[i-1][j][1]时

解释:f[i][j][0]:前i排中交错放了j次,并且第i排放满时,最多放的个数。它可以由上一排也放满了时转移过来,因为这排和上一排都放了s个,所以加错次数不变,上一排k的状态是0,即:f[i-1][j][0]。也可以由上一行没有放满的状态,这时交错次数增加了1,上一排k的状态是1,所以由f[i-1][j-1][1]转移过来。这两者取一个最大值后加上这一排放置的个数就作为f[i][j][0]的值。高度g的计算是根据前后的k是否一样转移的(k相等,增加2r,否则增加√3r)。

同理有:
f[i][j][1]=f[i-1][j-1][0]+s-1
g[i][j][1]=g[i-1][j-1][0]+√3*r

解释:这里的转移状态只有一个,原因是当前第i排放的是s-1个,如果上一排还是放的s-1个,肯定不是最优的,因为这样不仅占用2r高,这排还少放一个,怎么也划不来。所以不用从f[i-1][j][1]转移过来。

最终答案就是所有g[i][j][k]<=n的状态中的max(f[i][j][k])

有了答案放置方法就可以倒推回去了,如10*10的正方形,直径是1的圆,最终答案是106。这个答案在f[11][8][0]里面,那么可以得出共放了11排,其中交错放置了8次。复原放法很简单,前9排交错放(共8次交错)。
即:第一排放10个,第二排放9个,第三排放10个,第四排放9个…,第九排放10个,之后的10-11排都放10个。

用c++实现如下:

#include<iostream>
#include<cstdio>
#include<math.h>
using namespace std;
const int N=500;
int f[N][N][2];
double g[N][N][2];
int main()
{while(true){int n,d;cout<<"请输入正方形的边长:";cin>>n;cout<<"请输入圆的直径: ";cin>>d;cout<<endl;int nn=n;int D=d;if(d%2!=0)n*=2,d*=2;double r=d/2;int s=n/d;int ans=0;double sqrt3=sqrt(3);//cout<<n<<" "<<d<<" "<<sqrt3<<" "<<s<<endl;int ii,jj;for(int i=1; i<=n; i++){for(int j=0; j<=i; j++){if(j>0&&f[i-1][j-1][1]>f[i-1][j][0]){f[i][j][0]=f[i-1][j-1][1]+s;g[i][j][0]=g[i-1][j-1][1]+sqrt3*r;}else{f[i][j][0]=f[i-1][j][0]+s;g[i][j][0]=g[i-1][j][0]+2*r;}if(j>0){f[i][j][1]=f[i-1][j-1][0]+s-1;g[i][j][1]=g[i-1][j-1][0]+sqrt3*r;}if(g[i][j][0]<=n)if(ans<f[i][j][0])ans=f[i][j][0],ii=i,jj=j;if(g[i][j][1]<=n)if(ans<f[i][j][1])ans=f[i][j][1],ii=i,jj=j;}}printf("边长为%d的正方形圆的直径为%d,可以放下:  %d   个\n",nn,D,ans);printf("共放置 %d 排,其中交错放置 %d 次\n\n",ii,jj);}}

经过测试,结果如下:
在这里插入图片描述

这篇关于边长为n的正方形最多可以放下多少个半径为r的圆?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/337928

相关文章

LeetCode:64. 最大正方形 动态规划 时间复杂度O(nm)

64. 最大正方形 题目链接 题目描述 给定一个由 0 和 1 组成的二维矩阵,找出只包含 1 的最大正方形,并返回其面积。 示例1: 输入: 1 0 1 0 01 0 1 1 11 1 1 1 11 0 0 1 0输出: 4 示例2: 输入: 0 1 1 0 01 1 1 1 11 1 1 1 11 1 1 1 1输出: 9 解题思路 这道题的思路是使用动态规划

【无线通信发展史⑧】测量地球质量?重力加速度g的测量?如何推导单摆周期公式?地球半径R是怎么测量出来的?

前言:用这几个问答形式来解读下我这个系列的来龙去脉。如果大家觉得本篇文章不水的话希望帮忙点赞收藏加关注,你们的鼓舞是我继续更新的动力。 我为什么会写这个系列呢? 首先肯定是因为我本身就是一名从业通信者,想着更加了解自己专业的知识,所以更想着从头开始了解通信的来源以及在每一个时代的发展进程。 为什么会从头开始写通信? 我最早是学习了中华上下五千年,应该说朝代史,这个算个人兴趣,从夏

3127. 构造相同颜色的正方形(24.8.31)

题目 给你一个二维 3x3 的矩阵 grid,每个格子都是一个字符,要么是 'B' ,要么是 'W'。字符 'W' 表示白色,字符 'B' 表示黑色。 你的任务是改变至多一个格子的颜色,使得矩阵中存在一个 2x2 颜色完全相同的正方形。 如果可以得到一个相同颜色的 2x2 正方形,那么返回 true ,否则返回 false 示例 1: 输入: grid=["B","W","B"],["B",

已知弧度和半径,如何确定两点之间的距离?

如果已知弧度(通常表示为 θ)和半径(表示为 r),可以使用以下几何关系来确定圆弧上的两点之间的实际线性距离。 圆弧的长度(即两点之间的距离)可以通过以下公式计算: 弧长=r×θ 其中: θ 是以弧度为单位的角度(不是度数)。r 是圆的半径。结果是圆弧的长度,即两点沿着圆的路径的实际距离。 弧度和度数之间的转换关系是: 1 弧度=180/π​  度 如果角度是以度数给出的

Gridview图片正方形

现在在Android应用中,GridView中每个Item都是正方形的场景越来越常见。比如 陌陌 的搜索结果界面 陌陌的搜索界面显示 Android手机和IPhone不同, IPhone硬件是苹果自己出的,屏幕尺寸基本没啥太大差别,所以很好适配。 而Android就不一样了,中高低档手机都有,屏幕尺寸严重不统一,如何做到一种实现适配各种Android手机屏幕才是关键。 今天

MATLAB 计算三角形的外接圆心和半径(84)

MATLAB 计算三角形的外接圆心和半径(84) 一、算法介绍二、算法实现1.代码 一、算法介绍 计算三角形的外接圆心和半径,可视化显示结果 二、算法实现 1.代码 % 设置三个点的坐标A = [1, 1];B = [4,

第五章-OpenMV4 色块识别的图形圆形 正方形识别、 黑色红色识别颜色、坐标识别

项目比赛中需要识别黑色圆形和黄色方形状 要是识别的圆形 openmv代码如下代码带了阈值如何更改阈值 可以使用下面方法 这里是循迹 把循迹线调节成白色就是颜色追踪阈值 把线 调整成 import sensor, image, timesensor.reset() # 重置图像传感器sensor.set_pixformat(sensor.RGB565) # 设置像素格式为RG

任意半径局部直方图类算法在PC中快速实现的框架。

转自: 任意半径局部直方图类算法在PC中快速实现的框架。   在图像处理中,局部算法一般来说,在很大程度上会获得比全局算法更为好的效果,因为他考虑到了图像领域像素的信息,而很多局部算法可以借助于直方图获得加速。同时,一些常规的算法,比如中值滤波、最大值滤波、最小值滤波、表面模糊等等都可以通过局部直方图进行加速。而传统的获取局部直方图计算量很大,特别是半径增加时,耗时会成平方关系增加。一些局

[Mdfs] lc473. 火柴拼正方形(剪枝优化+经典题+好题)

文章目录 1. 题目来源2. 题目解析 1. 题目来源 链接:473. 火柴拼正方形 拔高、证明: [dfs] aw167. 木棒(dfs剪枝与优化+分类讨论+思维+好题) 2. 题目解析 水一篇。和之前的一个问题一模一样,在此不再赘述,写出来方便搜索。 [Mdfs] lc698. 划分为k个相等的子集(剪枝优化+经典题+好题) 时间复杂度:此类 dfs 和剪枝

polarctf靶场【四方密码题】【CRYPTO】不一样的四四方方、四个正方形

[CRYPTO]不一样的四四方方 考点:四方密码 在线网站: https://www.metools.info/code/four-square244.html 或者https://wtool.com.cn/four.html 请开始你的表演(密文):jilinjingcha注意:正确的密钥后面最后一个字母不要!!!key1:informationkey2:engineering