hdu5303(15年多校集训第二轮1004题delicious apple)
2015-07-27 11:20
387 查看
题目大意:有一个长度为l环路上边有坐标,你有个容量为k的篮子,你的房子位于坐标0点,其他坐标处有n棵苹果树,告诉你苹果树的位置和苹果树上的苹果的数目,问你取完所有苹果的最短路程。
解题思路:一开始没做出来,看了学车中学的题解,恍然大悟。首先,把环路剖开来看,这样就有两个半边了,分别对两个半边进行贪心(先拿最远的),又因为它是个环路,可以走一圈,所以在找下走一圈的情况;
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn=2000000+10000;
typedef long long LL;
int t,l,n,k,x[maxn];
int a1[maxn],n1,a2[maxn],n2;
LL ans,su1[maxn],su2[maxn];//半边贪心的结果
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&l,&n,&k);
int cnt=0;
for(int i=1; i<=n; i++)
{
int dis,num;
scanf("%d%d",&dis,&num);
for(int j=1; j<=num; j++)
x[++cnt]=dis;
}
k=min(k,cnt);
n1=n2=0;
for(int i=1; i<=cnt; i++)
{
if(x[i]*2<l) a1[++n1]=x[i];
else a2[++n2]=l-x[i];
}
sort(a1+1,a1+n1+1);
sort(a2+1,a2+n2+1);
su1[0]=su2[0]=0;
//对两个半边进行贪心
for (int i=1; i<=n1; i++)
if(i<=k)su1[i]=a1[i];
else su1[i]=a1[i]+su1[i-k];
for (int i=1; i<=n2; i++)
if(i<=k)su2[i]=a2[i];
else su2[i]=a2[i]+su2[i-k];
ans=(su1[n1]+su2[n2])*2;
//走一圈的情况
for (int i=0; i<=n1 && i<=k; i++)
{
int left=n1-i,right=max(0,n2-(k-i));//右边拿i个,左边k-i个
ans=min(ans,l+(su1[left]+su2[right])*2);
}
printf("%lld\n",ans);
}
return 0;
}
解题思路:一开始没做出来,看了学车中学的题解,恍然大悟。首先,把环路剖开来看,这样就有两个半边了,分别对两个半边进行贪心(先拿最远的),又因为它是个环路,可以走一圈,所以在找下走一圈的情况;
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn=2000000+10000;
typedef long long LL;
int t,l,n,k,x[maxn];
int a1[maxn],n1,a2[maxn],n2;
LL ans,su1[maxn],su2[maxn];//半边贪心的结果
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&l,&n,&k);
int cnt=0;
for(int i=1; i<=n; i++)
{
int dis,num;
scanf("%d%d",&dis,&num);
for(int j=1; j<=num; j++)
x[++cnt]=dis;
}
k=min(k,cnt);
n1=n2=0;
for(int i=1; i<=cnt; i++)
{
if(x[i]*2<l) a1[++n1]=x[i];
else a2[++n2]=l-x[i];
}
sort(a1+1,a1+n1+1);
sort(a2+1,a2+n2+1);
su1[0]=su2[0]=0;
//对两个半边进行贪心
for (int i=1; i<=n1; i++)
if(i<=k)su1[i]=a1[i];
else su1[i]=a1[i]+su1[i-k];
for (int i=1; i<=n2; i++)
if(i<=k)su2[i]=a2[i];
else su2[i]=a2[i]+su2[i-k];
ans=(su1[n1]+su2[n2])*2;
//走一圈的情况
for (int i=0; i<=n1 && i<=k; i++)
{
int left=n1-i,right=max(0,n2-(k-i));//右边拿i个,左边k-i个
ans=min(ans,l+(su1[left]+su2[right])*2);
}
printf("%lld\n",ans);
}
return 0;
}
相关文章推荐
- Code Forces 558 A. Lala Land and Apple Trees(水~)
- Unity导入FBX文件部分模型丢失材质的BUG
- iOS Sprite Kit教程之真机测试以及场景的添加与展示
- android学习记录(三)百度地图错误---只有一个电话显示帧,没有地图内容。
- Swift学习笔记(十四)——字符,常量字符串与变量字符串
- Android学习笔记(0)
- MyBasketball 第一篇
- android bindService()
- android imageview围绕中心旋转动画
- iOS 性能优化:Instruments 工具的救命三招
- 测试你的 In-app Billing 程序
- iOS利用Runtime自定义控制器POP手势动画
- iOS DEV info 启动画面 icon
- 【Android】Android布局中实现圆角边框
- iOS tableView索引
- Iterator迭代器、Comparable、Comparator比较器
- android电池驱动(四)(自用)
- 简单实现listview可选择的列表(不用重写adapter)
- android电池驱动(五)(自用)
- Android SwipeToDismiss:左滑/右滑删除ListView条目Item