P2678 跳石头

P2678 跳石头

1.思路:
首先我们二分跳跃距离,然后把这个跳跃距离“认为”是最短的跳跃距离,然后去以这个距离为标准移石头。判断这个解是不是可行解。check函数去判断如果以这个距离为最短跳跃距离需要移走多少块石头,先不必考虑限制移走多少块,等全部拿完再把拿走的数量和限制进行比对,如果超出限制,那么这就是一个非法解,反之就是一个合法解

2.算法:
二分,贪心

3.时间复杂度:
o(nlogn)

4.AC代码:

#include <bits/stdc++.h>
#define endl '\n'

using namespace std;

const int N=5e4+10;

int a[N];
int n,m,k;

bool check(int x)//按照可以移走石头的数量划分二分区间
{
    int cnt=0;int j=0;
    for(int i=1;i<=m+1;i++)
    {
        if(a[i]-a[j]<x) cnt++;//统计移走的石头数量
        else j=i;
    }
    
    if(cnt>k) return false;//如果数量大于k不符合条件 false
    else return true;
}

int main()
{
    cin>>n>>m>>k;
    for(int i=1;i<=m;i++) cin>>a[i];
    a[m+1]=n;
    
    int l=1;//最短跳跃距离左边界:一个也不移动并且最近距离为1
    int r=n;//最短跳跃距离右边界:移走所有石头
    while(l<r)
    {
        int mid=l+r+1>>1;
        if(check(mid)) l=mid;
        else r=mid-1;
    }
    
    cout<<l<<endl;
    
    return 0;
}

p3853 路标设置

1.思路:
与上题类似,只需要逆向考虑一下即可

#include <iostream>

using namespace std;

typedef long long ll;

const int N=1e5+10;

int a[N];

int n,m,k;

bool check(int x)
{
    ll sum=0;//需要增加路标的数量
    for(int i=1;i<m;i++)
    {
        if(a[i+1]-a[i]>x)
        {
            //特殊判一下如果距离是x的倍数的话要减一
            if((a[i+1]-a[i])%x==0) sum+=(a[i+1]-a[i])/x-1;
            else sum+=(a[i+1]-a[i])/x;
        }
    }
    if(sum>k) return false;
    else return true;
}

int main()
{
    cin>>n>>m>>k;
    for(int i=1;i<=m;i++) cin>>a[i];
    
    int l=1;int r=a[m]-a[1];
    while(l<r)
    {
        ll mid=l+r>>1;
        if(check(mid)) r=mid;
        else l=mid+1;
    }
    
    cout<<l<<endl;
    
    return 0;
}
posted @   Eric`  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
点击右上角即可分享
微信分享提示