二分 POJ 2456--Aggressive cows

本文介绍了一种使用二分法解决牛棚布局问题的方法,旨在最大化牛之间的最小距离,避免牛因过于拥挤而变得好斗。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

                                                                                               Aggressive cows

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 20261 Accepted: 9604

Description

Farmer John has built a new long barn, with N (2 <= N <= 100,000) stalls. The stalls are located along a straight line at positions x1,...,xN (0 <= xi <= 1,000,000,000). 

His C (2 <= C <= N) cows don't like this barn layout and become aggressive towards each other once put into a stall. To prevent the cows from hurting each other, FJ want to assign the cows to the stalls, such that the minimum distance between any two of them is as large as possible. What is the largest minimum distance?

Input

* Line 1: Two space-separated integers: N and C 

* Lines 2..N+1: Line i+1 contains an integer stall location, xi

Output

* Line 1: One integer: the largest minimum distance

Sample Input

5 3
1
2
8
4
9

Sample Output

3

Hint

OUTPUT DETAILS: 

FJ can put his 3 cows in the stalls at positions 1, 4 and 8, resulting in a minimum distance of 3. 

Huge input data,scanf is recommended.

Source

USACO 2005 February Gold

题意:有n个栅栏,坐标为 x1,...,xN,有C头牛,把没头牛放在离其他牛尽可能远的地方,也就是最大化最近的两头牛。

类似的最大化最小值或者最小化最大值问题,用二分法解决。

第一种方法采用的是看栅栏 
栅栏排好序之后是 
栅栏坐标 1 2 4 8 9
下标     0 1 2 3 4
1——9这些栅栏里面根据坐标可以放牛
从头开始放 L=0 R=9;
用二分法,再次放的时候 mid=L+(R-L)/2,mid=4
假设间隔为4的话,在这些栅栏里面放牛,看C个牛是否能放开
 1 2 4 8 9
放    放 
如果放不开,证明间隔太大了;如果能放开,证明间隔合法但不能证明间隔是最大间隔,还要再试放
mid=4显然放不开,修改R的值,R=4;此时 L=0 R=4 mid=2; 
再试放牛,间隔为2
 1 2  4  8 9
放   放 放 
显然能放开 ,但是不能说明2就是最大的距离,还要继续试放牛 
修改L=2,R=4; mid=3
 1 2 4  8 9
放  放 放 
能放开,还是要继续放,
L=3,R=4;此时不再满足while循环条件while(R-L>1),
综上:当间隔为3时,是放牛的最大距离。 
 


#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<math.h>
using namespace std;
const int maxn=1e5;
int n,c;
int a[maxn];
int check(int dir)
{
	int cows=1;
	int precow=0;
	for(int i=1;i<n;i++) //看栅栏的下标 
	{
		if(a[i]-a[precow]>=dir)//如果后一个牛与前一个牛之间的距离达到了dir
		{
			cows++;//把牛放进去
			precow=i;//记录刚刚放入的牛的位置,方便再放下一个牛
		}
		if(cows>=c)
		{
			return 1;
		}
	}
	return 0;
}
int main()
{
	scanf("%d%d",&n,&c);
	for(int i=0;i<n;i++)
	{
		scanf("%d",&a[i]);
	}
	sort(a,a+n);
	int L=0,R=a[n-1];
	while(R-L>1)
	{
		int mid=L+(R-L)/2;
		if(check(mid))
		{
			L=mid;	
			cout<<"L="<<L<<endl;
		 } 

		else
		{
		 R=mid;			
		  cout<<"R="<<R<<endl;
		}

	}
	printf("%d\n",L);
	return 0;
}

第二种做法:看牛 
栅栏排好序之后是 
栅栏坐标 1 2 4 8 9
下标     0 1 2 3 4
把牛放入的坐标的范围是0 <= xi <= 1,000,000,000
所以最先放牛的位置是0,最后一个放牛的最远位置是1e9
L=0,R=1e9+10(通常把范围放大看,包括1e9)
在L--R的范围内二分,然后在check函数中,判断以mid距离放牛,是否能放开

#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<math.h>
using namespace std;
const int INF=1e9+10;
const int maxn=1e5;
int n,c;
int a[maxn];
bool check(int dir)
{
	int precow=0; //第一个放牛的位置,用precow来记录 
	for(int i=1;i<c;i++) //牛的个数,通过判断条件,看把牛放在哪个栅栏里 
	{
		  int j=precow+1;//后一个放牛的位置,用j来记录 
		while(j<n && a[j]-a[precow]<dir)//如果后一个放牛的位置没有越界,并且前一个放牛的位置与后一个放牛的位置之间的距离为dir,就不再循环 
		{
		      j++;		
		//	  cout<<"j="<<j<<endl;	
		}
		if(j>=n) //判断是否越界 
		  return false;
		else
		  precow=j;
	}
	return true;
}
int main()
{
		scanf("%d%d",&n,&c);
		 int ans;
	for(int i=0;i<n;i++)
	{
		scanf("%d",&a[i]);
	}
	sort(a,a+n);
	int L=0,R=INF;//R=a[n-1]也是可以的,只不过范围大小不同 
	while(R-L>1)
	{
		int mid=L+(R-L)/2;
		if(check(mid))
		{
			L=mid;	
		//	cout<<"L="<<L<<endl;
		 } 

		else
		{
		 R=mid;			
		  //cout<<"R="<<R<<endl;
		}

	}
	printf("%d\n",L);
	/*这样写二分,最后输出的结果不是L或者R,而是L+1或者L-1
	  所以我们应该加一个计数变量ans来记录mid 
	 		 while(L<=R)
	{
		int mid=L+(R-L)/2;
		if(check(mid))
		{
		     ans=mid; //要在上面定义ans 
			L=mid+1;	
		//	cout<<"L="<<L<<endl;
		 } 

		else
		{
		    R=mid-1;			
		  //cout<<"R="<<R<<endl;
		}
	}
	printf("%d\n",ans);
	*/
	return 0;
}

注意的点:

1.写二分的方法:用的方法不同,输出不同。

2.看分栅栏和分牛两种方法,

资源下载链接为: https://pan.quark.cn/s/67c535f75d4c 在机器人技术中,轨迹规划是实现机器人从一个位置平稳高效移动到另一个位置的核心环节。本资源提供了一套基于 MATLAB 的机器人轨迹规划程序,涵盖了关节空间和笛卡尔空间两种规划方式。MATLAB 是一种强大的数值计算与可视化工具,凭借其灵活易用的特点,常被用于机器人控制算法的开发与仿真。 关节空间轨迹规划主要关注机器人各关节角度的变化,生成从初始配置到目标配置的连续路径。其关键知识点包括: 关节变量:指机器人各关节的旋转角度或伸缩长度。 运动学逆解:通过数学方法从末端执行器的目标位置反推关节变量。 路径平滑:确保关节变量轨迹连续且无抖动,常用方法有 S 型曲线拟合、多项式插值等。 速度和加速度限制:考虑关节的实际物理限制,确保轨迹在允许的动态范围内。 碰撞避免:在规划过程中避免关节与其他物体发生碰撞。 笛卡尔空间轨迹规划直接处理机器人末端执行器在工作空间中的位置和姿态变化,涉及以下内容: 工作空间:机器人可到达的所有三维空间点的集合。 路径规划:在工作空间中找到一条从起点到终点的无碰撞路径。 障碍物表示:采用二维或三维网格、Voronoi 图、Octree 等数据结构表示工作空间中的障碍物。 轨迹生成:通过样条曲线、直线插值等方法生成平滑路径。 实时更新:在规划过程中实时检测并避开新出现的障碍物。 在 MATLAB 中实现上述规划方法,可以借助其内置函数和工具箱: 优化工具箱:用于解决运动学逆解和路径规划中的优化问题。 Simulink:可视化建模环境,适合构建和仿真复杂的控制系统。 ODE 求解器:如 ode45,用于求解机器人动力学方程和轨迹执行过程中的运动学问题。 在实际应用中,通常会结合关节空间和笛卡尔空间的规划方法。先在关节空间生成平滑轨迹,再通过运动学正解将关节轨迹转换为笛卡
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值