Codeforces Round #501 (Div. 3) D Walking Between Houses

翻译

给你一条数轴(出题人很喜欢数轴啊),上面有排列着 n 个点,编号为 1 n (你开始在 1 )。每次你要从一个点移动到另一个点(可以重复)。移动距离为两点坐标之差的绝对值,问你是否能否在 k 次机会内里一共移动 s 距离,并输出方案。

思路

第四题还是比较难的,赛后想了几分钟时才有头绪。

毫无疑问还是贪心(出题人很喜欢贪心啊)!那么我们分类讨论,先看不合法的情况

  • 无论如何走你也走不到那个距离

  • 无论如何走你也会走超那个距离

看来只要能走到那个距离除外都是不合法的,因此就一个走超和走不到(我没废话!)。

那么如何解决?很简单,走不到就是每次你从最左边走到最右边,再从最右边走到最左边,这样循环下去,一直到你走完了还不到。

走超了就是你每次走一个距离,进行 k 次后还是大于 s

那么这两个代码好写极了,不用我教你吧 ^_^

到了合法的情况,受到不合法的启发,我们可以想到这样的方法:每一次啊,先从最左边走到最右边,再从最右边走到最左边,循环下去,一直到你剩下的距离不足 n 1 ( n 1 就是数轴两个端点间的距离)的时候啊,直接走完即可(由于在此期间你只会位于数轴的两个端点)。

但是不会那么简单的 Q A Q ,直接走完可不行啊,如果要走 32 那么远, 4 下子走完,数轴有 11 个点。照我们说的,当还有两个长度的时候,我们一步走完,呀!怎么还有一下!!

扫描二维码关注公众号,回复: 2675986 查看本文章

所以说,我们可以这样想:当剩下的距离不足 n 1 的时候,我们尝试分成多部走,很多种方法,我的有点麻烦,某位大佬写的是:走 s k s 是剩下的距离)的步数。感觉自己恍然大悟了(不懂你可以算算,由于是 s k ,这样就巧妙的拆分成了多部分)!

一定要用long long C F 的题就这个尿性)!

恐怕上述的方法是最简单的方法之一了吧,上代码(有两个细节在代码里注释了):

Code

#include<iostream>
using namespace std;
int main()
{
    long long n,k,s,a=1;
    cin>>n>>k>>s;
    if(s>(n-1)*k||k>s)
        return cout<<"NO"<<endl,0;
    cout<<"YES"<<endl;
    while(k--)
    {
        int r=min(s-k,n-1);//选区n-1与s-k中最小的,因为当s-k比n-1大的时候,我们要先消去 
        s-=r;
        if(a+r<=n)//看看往哪个方向走。 
            a+=r;
        else a-=r;
            cout<<a<<" ";
    }
    return 0;  
}

猜你喜欢

转载自blog.csdn.net/qq_39984146/article/details/81334586