hdu4004 Frog’s Game【二分+贪心】

The Frog's Games

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)
Total Submission(s): 5667    Accepted Submission(s): 2724


Problem Description
The annual Games in frogs' kingdom started again. The most famous game is the Ironfrog Triathlon. One test in the Ironfrog Triathlon is jumping. This project requires the frog athletes to jump over the river. The width of the river is L (1<= L <= 1000000000). There are n (0<= n <= 500000) stones lined up in a straight line from one side to the other side of the river. The frogs can only jump through the river, but they can land on the stones. If they fall into the river, they
are out. The frogs was asked to jump at most m (1<= m <= n+1) times. Now the frogs want to know if they want to jump across the river, at least what ability should they have. (That is the frog's longest jump distance).
 

Input
The input contains several cases. The first line of each case contains three positive integer L, n, and m.
Then n lines follow. Each stands for the distance from the starting banks to the nth stone, two stone appear in one place is impossible.
 

Output
For each case, output a integer standing for the frog's ability at least they should have.
 

Sample Input
  
  
6 1 2 2 25 3 3 11 2 18
 

Sample Output
  
  
4 11
 



开始的想法是递归做……

然而题目规模这么大,必然是TLE的大哭



百度了一下…

因为这个题规模真的不小…L<=1000000000

所以呢,是可以用二分的

对步长进行二分并带入判断。

判断的时候用到了贪心,尽量调到最远的距离

判断函数:

1.判断这个步长能不能跳过去,M*i<L?

2.从1开始判断。

   2.0  步数++;

    2.1  步长小于相邻两个石头的距离,return false;

    2.2  从当前的步循环判断可以跳到的最远石头。

    2.3  跳(变当前坐标)

    2.4  判断步数够不够。

#include <cstdio>
#include <algorithm>
using namespace std;
#define maxn 500005
int L,N,M;
int dis[maxn];

bool check(int x){		//1.判断步长是否可以 
	if(x*M<L){
		return false;
	} 
	int step=0, i=1, pre=0;
	while(i<=N+1){//2.从头开始跳跃
		step++;
		if(x<dis[i]-dis[i-1])	return false;//不能跳过去 
		
		while(i<=(N+1)&&x>=dis[i]-dis[pre]) i++;//找能跳到的最远距离 
		pre=i-1;								//贪心 
		
		if(step>M) return false;
		
	}
	return true; 
}


int main(){
	while(scanf("%d%d%d",&L,&N,&M)!=EOF){
		dis[0]=0;
		for(int i=1;i<=N;i++){
			scanf("%d",&dis[i]);
		} 
		dis[N+1]=L;
		sort(dis+1,dis+N+1);
		
		int l=0,r=L;
		while(l<=r){
			int mid=(l+r)/2;
			if(check(mid)){
				//可以缩小距离
				r=mid-1; 
			}else{
				//不可以就扩大距离 
				l=mid+1;
			}
		}
		printf("%d\n",l);
	}
	
	return 0;
}






开始的想法是递归做……

然而题目规模这么大,必然是TLE的大哭

我的渣代码也先放上来……

//TLE的代码……

#include <cstdio>
#include <algorithm>
using namespace std;
#define inf 1000000002
#define maxn 500005
#define max(x,y) x>y?x:y
#define min(x,y) x<y?x:y
long A[maxn];
long L,n,M,ans;

void fun(long last,long now,long m){
	if(m>min) return ;
	//剩余,目前坐标,最大步数 
	if(last==0&&now!=n){		//找不到 
		return;
	}
	else if(now==n){
		ans=min(ans,m);
	} 
	for(long k=1;now+k<=n;k++){
		m=max(m,A[now+k]-A[now]);
		fun(last-1,k+now,m);
	}	
}
 
int main(){
	while(scanf("%ld%ld%ld",&L,&n,&M)!=EOF){
		min=inf; 
		for(long i=0;i<n;i++){
			scanf("%ld",&A[i]);
		}
		sort(A,A+n);
		A[n]=L;
		ans=inf;
		for(long j=0;j<=n;j++){
			fun(M-1,j,A[j]);
		}
		
		printf("%ld\n",ans);
	}
	return 0;
}
 


百度了一下…

因为这个题规模真的不小…L<=1000000000

所以呢,是可以用二分的

对步长进行二分并带入判断。

判断的时候用到了贪心,尽量调到最远的距离

判断函数:

1.判断这个步长能不能跳过去,M*i<L?

2.从1开始判断。

   2.0  步数++;

    2.1  步长小于相邻两个石头的距离,return false;

    2.2  从当前的步循环判断可以跳到的最远石头。

    2.3  跳(变当前坐标)

    2.4  判断步数够不够。

#include <cstdio>
#include <algorithm>
using namespace std;
#define maxn 500005
int L,N,M;
int dis[maxn];

bool check(int x){		//1.判断步长是否可以 
	if(x*M<L){
		return false;
	} 
	int step=0, i=1, pre=0;
	while(i<=N+1){//2.从头开始跳跃
		step++;
		if(x<dis[i]-dis[i-1])	return false;//不能跳过去 
		
		while(i<=(N+1)&&x>=dis[i]-dis[pre]) i++;//找能跳到的最远距离 
		pre=i-1;								//贪心 
		
		if(step>M) return false;
		
	}
	return true; 
}


int main(){
	while(scanf("%d%d%d",&L,&N,&M)!=EOF){
		dis[0]=0;
		for(int i=1;i<=N;i++){
			scanf("%d",&dis[i]);
		} 
		dis[N+1]=L;
		sort(dis+1,dis+N+1);
		
		int l=0,r=L;
		while(l<=r){
			int mid=(l+r)/2;
			if(check(mid)){
				//可以缩小距离
				r=mid-1; 
			}else{
				//不可以就扩大距离 
				l=mid+1;
			}
		}
		printf("%d\n",l);
	}
	
	return 0;
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值