lightoj Winter 1084 (dfs&&bfs求最少堆数) 好题

47 篇文章 1 订阅
39 篇文章 0 订阅
LightOJ - 1084
Time Limit: 2000MSMemory Limit: 32768KB64bit IO Format: %lld & %llu

Submit Status

Description

Winter is coming. In a land far away, N men are spending the nights in a valley in a largest field. The valley is so narrow that it can be considered to be a straight line running east-to-west.

Although standing in the valley does shield them from the wind, the group still shivers during the cold nights. They, like anyone else, would like to gather together for warmth.

Near the end of each day, each man i finds himself somewhere in the valley at a unique location Li. The men want to gather into groups of three or more persons since two persons just aren't warm enough. They want to be in groups before sunset, so the distance K each man can walk to form a group is limited. Determine the smallest number of groups the men can form.

Input

Input starts with an integer T (≤ 15), denoting the number of test cases.

Each case starts with two integers N (1 ≤ N ≤ 105) and K (1 ≤ K ≤ 106). Each of the next N line contains an integer Li (1 ≤ Li ≤ 108).

Output

For each case, print the case number and smallest number of groups the men can gather into. If there is no way for all the men to gather into groups of at least size three, output -1.

Sample Input

2

6 10

2

10

15

13

28

9

3 1

1 10 20

Sample Output

Case 1: 2

Case 2: -1

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define INF 0x3f3f3f3f
#define N 100010
using namespace std;
int n,k;
int a[N];
int f[N];
int dfs(int x)
{
	if(x>=n)
		return 0;
	if(f[x]!=-1)
		return f[x];
	int &ans=f[x];
	int m=upper_bound(a,a+n,a[x]+k)-a;
	ans=INF;
	if(m-x>=3)
		ans=min(ans,dfs(m)+1);
	if(m-x>=4)
		ans=min(ans,dfs(m-1)+1);
	if(m-x>=5)
		ans=min(ans,dfs(m-2)+1);
	return ans;
}
int main()
{
	int t,T=1;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&k);
		k<<=1;
		int i;
		for(i=0;i<n;i++)
			scanf("%d",&a[i]);
		sort(a,a+n);
		memset(f,-1,sizeof(f));
		int ans=dfs(0);
		if(ans==INF)
			ans=-1;
		printf("Case %d: %d\n",T++,ans);
	}
}

//bfs解

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#define N 100010
#define INF 0x3f3f3f3f
using namespace std;
int a[N];
int vis[N];
int n,k;
struct zz
{
	int x;
	int m;
}p,q;
int bfs()
{
	queue<zz>qq;
	memset(vis,0,sizeof(vis));
	p.m=0;p.x=0;
	qq.push(p);
	vis[0]=1;
	while(!qq.empty())
	{
		p=qq.front();
		qq.pop();
		if(p.m>=n)
			return p.x;
		int tmp=p.m;
		while(tmp<n&&a[tmp]-a[p.m]<=2*k)
			tmp++;
		int num=tmp-p.m;
		if(num>=3&&!vis[tmp])
		{
			q.m=tmp;
			q.x=p.x+1;
			qq.push(q);
			vis[tmp]=1;
		}
		if(num>=4&&!vis[tmp-1])
		{
			q.m=tmp-1;
			q.x=p.x+1;
			qq.push(q);
			vis[tmp-1]=1;
		}
		if(num>=5&&!vis[tmp-2])
		{
			q.m=tmp-2;
			q.x=p.x+1;
			qq.push(q);
			vis[tmp-2]=1;
		}
	}
	return -1;
}
int main()
{
	int t,T=1;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&k);
		for(int i=0;i<n;i++)
			scanf("%d",&a[i]);
		sort(a,a+n);
		int ans=bfs();
		printf("Case %d: %d\n",T++,ans);
	}
	return 0;
}

//看了上面两篇大神的,自己又写了一遍,感觉又收获不少。



 

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 100010
#define INF 0x3f3f3f3f
using namespace std;
int a[N];
int f[N];
int n,k;
int dfs(int x)
{
	if(x>=n)
		return 0;
	if(f[x]!=-1)
		return f[x];
	int m=upper_bound(a,a+n,a[x]+k)-a;
	int ans=INF;
	if(m-x>=3)//一个都不给 
		ans=min(ans,dfs(m)+1);
	if(m-x>=4)//分一个给后面 
		ans=min(ans,dfs(m-1)+1);
	if(m-x>=5)//分两个给后面 
		ans=min(ans,dfs(m-2)+1);
	f[x]=ans;
	return f[x];
}
int main()
{
	int t,T=1;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&k);
		k<<=1;
		for(int i=0;i<n;i++)
			scanf("%d",&a[i]);
		sort(a,a+n);
		memset(f,-1,sizeof(f));
		int ans=dfs(0);
		if(ans==INF)
			ans=-1;
		printf("Case %d: %d\n",T++,ans);
	}
	return 0;
}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值