MT3038 植发

简介: MT3038 植发

24e309f500a04e5487b01de99b07d936.jpg

0fd30343d2a34a979e7f0d026167d48e.jpg

思路:

有两个点可以取头发,每个头发寿命不同。

先看点(0,0),按寿命由小到大排序(先考虑寿命短的可以移植到哪里)。

(0,0)点头发放置的位置应该让(0,m)点的头发可以尽可能多的放置(例如(0,0)点有一根头发既可以放置在(1,5)点,又可以放置在(5,1)点,则会放置在(1,5)点)


代码:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e4 + 10;
struct node
{
    int x, y;
    int dis;
    bool operator<(const node &a) const
    { // 大根堆,重载<号
        return dis < a.dis;
    }
};
int a1[N], a2[N]; // 不同寿命头发有多少根
int n, m, k, l;
bool used[N][N];
vector<pair<int, int>> s1[N], s2[N]; // 存储不同距离下的点的坐标
priority_queue<node> down, up;       // 大根堆 down 和 up
int dist(int x1, int y1, int x2, int y2)
{
    return abs(x1 - x2) + abs(y1 - y2);
}
 
int main()
{
    cin >> n >> m;
    cin >> k;
    for (int i = 0; i < k; i++)
    { //(0,0)处头发
        int x;
        cin >> x;
        a1[x]++; // 存寿命为x的头发有多少根
    }
    cin >> l;
    for (int i = 0; i < l; i++)
    { //(0,m)处头发
        int x;
        cin >> x;
        a2[x]++;
    }
    for (int i = 1; i <= n; i++)
    { // 对于每一个点,都计算离(0,0)和(0,m)的距离
        for (int j = 1; j <= m; j++)
        { // s1s2存不同距离下有哪些点
            s1[dist(i, j, 0, 0)].push_back({i, j});
            s2[dist(i, j, 0, m + 1)].push_back({i, j});
        }
    }
    int flag = 0;
    // 先看离(0,0)的距离
    for (int i = 1; i <= n + m; i++)
    { // 遍历每一个距离 (i不仅为距离,还为要消耗的寿命)
        for (int j = 0; j < s1[i].size(); j++)
        { // 对于指定的距离,把符合的点放到队列里
            int x = s1[i][j].first;
            int y = s1[i][j].second;
            node tmp;
            tmp.dis = dist(x, y, 0, m + 1), tmp.x = x, tmp.y = y;
            down.push(tmp);
        }
        for (int j = 0; j < a1[i]; j++)
        { // 对于同一个寿命,可以放的位置
            if (down.empty())
            { //(0,0)的头发已放完
                flag = 1;
                break;
            }
            // 取出能放的最远的点
            int tmpx = down.top().x;
            int tmpy = down.top().y;
            down.pop();
            used[tmpx][tmpy] = 1; // 记录该位置已被使用
        }
        if (flag == 1)
        {
            break;
        }
    }
    // 先看离(0,m)的距离
    for (int i = 1; i <= n + m; i++)
    { // 遍历每一个距离i
        for (int j = 0; j < s1[i].size(); j++)
        {
            int x = s2[i][j].first;
            int y = s2[i][j].second;
            if (used[x][y] == 1)
            { // 若该位置已经被使用,跳过
                continue;
            }
            node tmp;
            tmp.dis = dist(x, y, 0, 0), tmp.x = x, tmp.y = y;
            up.push(tmp);
        }
        for (int j = 0; j < a2[i]; j++)
        {
            if (up.empty())
            {
                flag = 1;
                break;
            }
            int tmpx = up.top().x;
            int tmpy = up.top().y;
            up.pop();
            used[tmpx][tmpy] = 1;
        }
        if (flag == 1)
        {
            break;
        }
    }
    if (flag == 0)
        cout << "YES";
    else
        cout << "NO";
    return 0;
}


相关文章
|
23天前
|
人工智能 BI
MT3018 斐波那契数列
MT3018 斐波那契数列
|
传感器 芯片 内存技术
【玩转RT-Thread】ART-Pi 网络时钟(上)
【玩转RT-Thread】ART-Pi 网络时钟
108 0
|
开发工具 C++
【玩转RT-Thread】ART-Pi 网络时钟(下)
【玩转RT-Thread】ART-Pi 网络时钟
131 0