题目链接:https://ac.nowcoder.com/acm/contest/917/A
题意:
有n个羊,每只羊可以自己可以跳x[i]米,踩在别的羊身上可以跳y[i]米,每只羊只可以被别的羊踩一次每只羊也可以不被踩或者不踩别的羊。现在要跳过长为s米的峡谷,问最优情况下,有多少只羊可以越过峡谷。
题解:
贪心策略:
如果羊自己可以过,就让他自己过(没必要为了让一只羊过在多浪费一只羊)
如果羊的x[i]+y[i]<s,则表明即使他踩在别的羊身上也过不去。所以直接把这些羊当作跳板(被踩的羊)。这种羊的x[i] 放入a数组中。
如果羊的x[i]+y[i]>=s,则表示他可以踩在别的羊身上过去,只要被踩得羊的x[i]小于等于他自己的x[i]且与y[i]相加大于等于s即可越过峡谷此时则配对成功。这种羊的y[i]放在b数组中。
将a中的值从小到大排列,b中的值从大到小排列,每一个b中的值取找一个能够满足他的最小的a。
因为b中的值都满足x[i]+y[i] >=s,所以只要a[i]+b[j]>=s,那么s-y[i]这个点一定在a[i]和x[i]内,所以b[j]这只羊一定可以踩在a[i]这只羊身上,既可以越过峡谷。
附上AC代码:
#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int maxn=1e6+5;
LL a[maxn],b[maxn];
LL s;
int n,cnta=0,cntb=0;
bool cmp(LL a,LL b)
{
return a>b;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>s;
LL ans=0,x,y;
for(int i=0;i<n;i++)
{
cin>>x>>y;
if(x>=s) ans++;
else if(x+y<s) a[cnta++]=x;//不能到达对岸,直接当作跳板
else b[cntb++]=y;//可以跳到对岸,则计入b中
}
sort(a,a+cnta);//从小到大排序
sort(b,b+cntb,cmp);//从大到小排序
//贪心:最大的先和最小的配对
int i=0,j=0;
for(;i<cnta&&j<cntb;j++)
{
LL tmp=b[j];
while(i<cnta)
{
//因为保证了b可以过即x+y>=s,所以如果y+a[i]>=s,那么x一定和a[i]有交集且保证在那个点跳跃可以飞过峡谷
if(tmp+a[i]>=s)//如果第bj个踩在第ai个上可以过,则数量加一
{
ans++;
i++;
break;
}
else
i++;
}
}
if(j==cntb)//如果可以飞过峡谷的都配对完了,那么直接输出结果
cout<<ans;
else//如果没有配对玩,则直接两两配对
cout<<ans+(cntb-j)/2;
return 0;
}
欢迎评论!