AcWing每日一题 挤奶顺序

Farmer John 有 N 头奶牛,编号为 1 … N 1…N 1N.

他每天都要给他的奶牛们挤奶。奶牛的社会结构非常复杂,其结构有两个关键特性。

首先,有 M M M 头奶牛的地位等级分明,按照地位越高越早挤奶的规则,这些奶牛的相对挤奶顺序是固定的。

此外,有 K K K 头奶牛的具体挤奶顺序也是固定的,比如,奶牛 4 4 4 必须在所有奶牛中的第二位挤奶。

幸运的是,Farmer John 总是能够以一种满足所有这些情况的顺序给他的奶牛们挤奶。

不幸的是,奶牛 1 1 1 最近生病了,所以 Farmer John 想要尽早给这头奶牛挤奶,使得她可以回到牛棚休息。

请帮助 Farmer John 求出奶牛 1 可以在挤奶顺序中出现的最早位置。

输入格式
第一行包含 N , M , K N,M,K NMK,表示 Farmer John 有 N N N 头奶牛,其中 M M M 头形成了社会阶层, K K K 头需要在挤奶顺序中处于一个特定的位置。

下一行包含 M M M 个不同的整数 mi。在这一行出现的奶牛必须以与她们在这行出现的顺序相同的顺序进行挤奶。

下面 K K K 行,每行包含两个整数 c i c_i ci p i p_i pi,表示奶牛 c i c_i ci 一定要在第 p i p_i pi 位进行挤奶。

输入数据保证:在这些限制之下,Farmer John 能够建立一个符合要求的挤奶顺序。

输出格式
输出奶牛 1 1 1 可以在挤奶顺序中出现的最早位置。

数据范围
2 ≤ N ≤ 100 2≤N≤100 2N100,
1 ≤ M , K < N 1≤M,K<N 1M,K<N,
1 ≤ m i , c i , p i ≤ N 1≤m_i,c_i,p_i≤N 1mi,ci,piN

分析 本题着重考察了分类讨论
第二行给出的是相对顺序,第三行给出的是绝对顺序。因此
1.若1出现在绝对位置,则直接输出它即可
2.若1出现在相对位置,则可以贪心的考虑,若这个位置没有出现在绝对顺序里我们就放出现在1前面相对顺序里的元素,这样就可以尽早安排1号牛
3.若1既没有出现在相对位置,也没有出现在绝对位置,那么应该在绝对位置给定下从后往前安排相对顺序即可成立

#include<bits/stdc++.h>
using namespace std;

const int N = 110;
int q[N] , p[N] , st[N];
int n , m , k;

int main()
{
    bool flag = false;
    cin >> n >> m >> k;
    
    for (int i = 1; i <= m; ++ i)
    {
        cin >> q[i]; 记录下相对位置
        if (q[i] == 1) flag = true;
    }
    
    memset(p , -1 , sizeof p); 清空
    
    while(k --)
    {
        int a , b;
        cin >> a >> b;
        if (a == 1) 如果1出现在绝对位置那么就直接输出
        {
            cout << b << endl;
            return 0;
        }
        p[a] = b; 否则就记录绝对位置
        st[b] = true;这个点用过了
    }
    
    if (flag) 讨论1是否出现在相对顺序里
    {
        for (int i = 1 , j = 1; i <= m; ++ i)
        {
            while(st[j]) j ++; 绝对位置就填它
            if (p[q[i]] != -1) j = p[q[i]]; 然后安排相对顺序
            else
            {
                if (q[i] == 1)
                {
                    cout << j << endl;
                    return 0;
                }
                st[j] = true;
                j ++;
            }
        }
    }
    else
    {
        for (int i = m , j = n; i >= 1; -- i)
        {
            while(st[j]) j --;
            if (p[q[i]] != -1) j = p[q[i]];
            else
            {
                st[j] = true;
                j --;
            }
        }
        
        for(int i = 1; i <= n; ++ i)
            if (!st[i])
            {
                cout << i << endl;
                return 0;
            }
    }
    
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值