• 『题解』CF28A Bender Problem


    题意

    \(n\) 个钉子,从 \(1 \sim n\) 编号,有 \(m\) 条铁棒,要求用这些铁棒和钉子围成一个封闭的折线。要求铁棒不一定全部用完,铁棒必须平行于坐标轴。

    现在他要把铁棒弯成直角,这样中间的折叠点一个钉子,两头各一个钉子,要求折叠的这颗钉子之前必须是没有别的棒连接的(也就是空钉子),问怎么选棒,棒只能用一次。

    如果无法解决 Bender 的问题,请输出 NO 。否则,在第一行中输出 YES ,在第二行中输出 \(n\) 个数字,其中第 \(i\) 个数表示杆的数量,该折叠位置固定在第 \(i\) 个钉上;如果没有这样的杆,则输出 \(-1\)

    思路

    用铁棒把钉子框起来,每个铁棒只能折叠一次。

    由题意我们可以得出,如果一个铁棒在第 \(i\) 个钉子处折叠,那么第 \(i+1\) 个就一定不是折叠的。

    题目中钉子按顺序给出,所以我们只需要枚举每个钉子,判断是奇数或者偶数点,看是否满足即可。

    注意初始条件。

    CODE

    /*
    
    Name: CF28A Bender Problem
    
    Solution: 瞎搞
       
    
    By Frather_
    
    */
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <queue>
    #define ll long long
    #define InF 0x3f3f3f3f
    #define kMax 10e5
    #define kMin -10e5
    #define kMod 998244353
    using namespace std;
    /*==================================================快读*/
    inline int read()
    {
        int X = 0, F = 1;
        char CH = getchar();
        while (CH < '0' || CH > '9')
        {
            if (CH == '-')
                F = -1;
            CH = getchar();
        }
        while (CH >= '0' && CH <= '9')
        {
            X = (X << 3) + (X << 1) + (CH ^ 48);
            CH = getchar();
        }
        return X * F;
    }
    /*===============================================定义变量*/
    int n, m;
    
    const int _ = 10010;
    
    int x[_], y[_], rod[_], ans[_];
    bool vis[_];
    bool flag;
    /*=============================================自定义函数*/
    int Calc(int i, int j)
    {
        int x_ = abs(x[j] - x[(j + n - 1) % n]);
        int y_ = abs(y[j] - y[(j + n - 1) % n]);
        int _x = abs(x[j] - x[(j + 1) % n]);
        int _y = abs(y[j] - y[(j + 1) % n]);
        return x_ + y_ + _x + _y;
    }
    
    void prepare()
    {
        memset(ans, -1, sizeof(ans)); //判断是否折叠
        memset(vis, false, sizeof(vis));
        flag = true;
    }
    /*=================================================主函数*/
    signed main()
    {
        n = read();
        m = read();
        for (int i = 0; i < n; i++)
        {
            x[i] = read();
            y[i] = read();
        }
        for (int i = 0; i < m; i++)
            rod[i] = read();
    
        for (int i = 0; i < 2; i++)
        {
            prepare();
    
            for (int j = i; j < n; j += 2)
            {
                int dis = Calc(i, j); //当前钉子与前一个或后一个的距离
    
                for (int k = 0; k < m; k++)
                {
                    if (!vis[k] && rod[k] == dis)
                    {
                        vis[k] = true;
                        ans[j] = k + 1;
                        break;
                    }
                }
    
                if (ans[j] == -1)
                {
                    flag = false;
                    break;
                }
            }
            if (flag)
                break;
        }
        if (flag)
        {
            printf("YES\n%d", ans[0]);
    
            for (int i = 1; i < n; i++)
                printf(" %d", ans[i]);
            puts("");
        }
        else
            printf("NO\n");
        return 0;
    }
    
  • 相关阅读:
    OCP-1Z0-052-V8.02-116题
    OCP-1Z0-052-V8.02-6题
    OCP-1Z0-052-V8.02-5题
    使用rman恢复控制文件
    Matlab-质点的运动
    Matlab中checkerboard-创建棋盘图像(二)
    OCP-1Z0-052-V8.02-4题
    OCP-1Z0-052-V8.02-3题
    Matlab中checkerboard-创建棋盘图像(一)
    OCP-1Z0-052-V8.02-1题
  • 原文地址:https://www.cnblogs.com/Frather/p/14698424.html
Copyright © 2020-2023  润新知