Codeforces 1015D.Walking Between Houses

该博客详细分析了Codeforces 1015D问题,即在1到n的位置中,每次必须走到相对当前位置的另一个位置,探讨了如何用k步走完s距离的策略。通过贪心算法,博主首先尝试走最远距离,然后根据剩余步数和总距离判断可能的解,并分为三种情况讨论:x=0, y=0, 和 x,y均不为0。特别指出,当n=2时需要特殊处理,并解释了k过小或s过大时解不存在的情况。" 128171954,15718730,基于SpringBoot的小区宠物管理系统设计,"['spring boot', 'java', '数据库管理', '系统设计', '宠物服务']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:http://codeforces.com/contest/1015/problem/D

题意:给了1-n这n个位置,从1开始走,每次必须走到相对于当前位置的另外一个位置,问是否可以用k步走s的距离,每次走的距离为|pos1-pos2|(pos1为原位置,pos2为走到的位置)

分析:坑爹的大模拟。先贪心地走尽可能远的位置,我直接选取了左右两边,每次走n-1步,假设有x个这样的走法,剩下走了y步。可以得到x + y = k , x * (n - 1) + d = s 。x = (s - k) / (n - 2)。但是s-k不一定能被n-2整除呀,但是整数部分就是一定要走的了,不能整除的话会多出来不超过n-2的步子,y不为0的话我们就抽出一步走多余的步子,剩下的一步一步走就好啦。这里我分三种情况讨论,分别是x=0,y=0,x,y均不为0的情况。注意n=2要单独讨论一下。不满足的情况就是k太小或者s太大。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
ll res[maxn];
int main()
{
    ll n,k,s;
    cin>>n>>k>>s;
    if(k > s)
    {
        printf("NO\n");
        return 0;
    }
    if(s % (n - 1) == 0 && (s / (n - 1)) > k)
    {
        printf("NO\n");
        return 0;
    }
    if(s % (n - 1) != 0 && (s / (n - 1) + 1) > k)
    {
        printf("NO\n");
        return 0;
    }
    ll x = (s - k) / (n - 2),len;
    printf("YES\n");
    if(n == 2)
    {
        ll cnt = 0,pos = 2;
        int flag = 0;
        while(cnt < k)
        {
            res[++cnt] = pos;
            if(!flag)
                pos++;
            else
                pos--;
            if(pos == n + 1)
            {
                pos = n - 1;
                flag = !flag;
            }
            else if(pos == 0)
            {
                pos = 2;
                flag = !flag;
            }
        }
        len = cnt;
    }
    else
    {
        ll y = k - x;
        //printf("%I64d %I64d %I64d\n",x,y,jump);
        for(ll i = 1; i <= x; i++)
        {
            if(i % 2)res[i] = n;
            else res[i] = 1;
        }
        if(x == 0)
        {
            y--;
            ll jump = s - x * (n - 1) - y;
            res[1] = 1 + jump;
            ll cnt = x + 1,pos = jump;
            int flag = 0;
            while(cnt - x - 1 < y)
            {
                res[++cnt] = pos;
                if(!flag)
                    pos--;
                else
                    pos++;
                if(pos == n + 1)
                {
                    pos = n - 1;
                    flag = !flag;
                }
                else if(pos == 0)
                {
                    pos = 2;
                    flag = !flag;
                }
            }
            len = cnt;
        }
        else if(y == 0)
        {
            for(ll i = 1; i <= x; i++)
            {
                if(i % 2)res[i] = n;
                else res[i] = 1;
            }
            len = x;
        }
        else
        {
            y--;
            ll jump = s - x * (n - 1) - y;
            if(res[x] == 1)
            {
                res[x + 1] = 1 + jump;
                ll cnt = x + 1,pos = jump;
                int flag = 0;
                while(cnt - x - 1 < y)
                {
                    res[++cnt] = pos;
                    if(!flag)
                        pos--;
                    else
                        pos++;
                    if(pos == n + 1)
                    {
                        pos = n - 1;
                        flag = !flag;
                    }
                    else if(pos == 0)
                    {
                        pos = 2;
                        flag = !flag;
                    }
                }
                len = cnt;
            }
            else
            {
                res[x + 1] = n - jump;
                ll cnt = x + 1,pos = n - jump + 1;
                int flag = 0;
                while(cnt - x - 1 < y)
                {
                    res[++cnt] = pos;
                    if(!flag)
                        pos++;
                    else
                        pos--;
                    if(pos == 0)
                    {
                        pos = 2;
                        flag = !flag;
                    }
                    else if(pos == n + 1)
                    {
                        pos = n - 1;
                        flag = !flag;
                    }
                }
                len = cnt;
            }
        }
      }
   for(ll i = 1; i <= len; i++)
   {
        if(i == 1)printf("%I64d",res[i]);
        else printf(" %I64d",res[i]);
    }
    printf("\n");
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值