• 牛客编程巅峰赛S1第12场 王者B-上上下下(DP)


    题目链接:https://ac.nowcoder.com/acm/contest/6916/B
    CSDN食用链接:https://blog.csdn.net/qq_43906000/article/details/108035201

    题目描述

    牛牛是一位优秀的程序员。最近,牛牛在的公司要办年会了。
    牛牛所在的组要表演一个比较有意思的大合唱,程序员们站在第一排,产品经理们站在第二排。为了让年会节目更有吸引力,牛牛在设计站位上下了功夫:从左往右,程序员们由高到矮进行站位,而产品经理们则按由矮到高进行站位,两个队列的上下场方向也不一样,这样从上场、演唱到下场,整个队列看起来就像一个波浪开合,非常有趣。
    牛牛他们排练完就回去工作了,转眼就来到了年会当天。当大家换上了表演用的服装后,牛牛傻了眼:之前排练的时候大家穿的都是自己的鞋,这下统一更换成演出用的鞋之后,原来两个排好的队列不再按身高有序了!然而,表演马上就要开始了,由于站位和演出效果有关,大家的站位又不能进行调整,这可怎么办?
    聪明的牛牛想到了一个补救办法:如果能让相对站在同一列的产品经理和程序员互换位置,最后也能满足从左往右第一排从高到矮,第二排从矮到高,那也能满足演出效果。然而,就在这个关头,牛牛被叫去核对音乐和灯光了,他只好把这个任务交给你。他会把现在第一排和第二排的身高数据给你,请你告诉他最少需要交换几对演出成员才能满足之前的要求。如果怎么交换都不能满足,请你返回 -1。

    输入
    [5,4,3,2,1],[1,2,3,4,5]
    输出
    0
    说明
    显然,这个排列已经满足要求,不需要交换。

    输入
    [1,2,3,4,5],[5,4,3,2,1]
    输出
    4

    输入
    [3,2,1],[1,3,3]
    输出
    -1

    说明
    别忘了如果怎么交换都不能满足要求,你应该返回 -1。
    备注:
    注意,本题中的高矮关系为严格大于小于关系,即 [1,2,3] 可以看作由矮到高,但是 [1,3,3] 不行。

    数据范围:

    • 对于 20% 的数据,(1le Nle 16)
    • 对于 60% 的数据,(1le Nle 10^3)
    • 对于 100% 的数据,(1le Nle 10^5)

    对于 100% 的数据,两个数组的大小均恰好为 ,且两个数组 ({a_i}, {b_i})的元素均满足 (1le a_i, b_ile10^9)

    emmmm,一个很明显的DP,他肯定有一个状态来枚举每一位,再来一个状态来枚举每一位换不换,那么就可以得到(dp[n][0/1])这个dp状态了。接下来就是转移方程了,很明显每个位置有换与不换两种情况,我们分开讨论,对于该位置不换的情况,也就是从上一个状态转移到(dp[i][0]),那么我们还得看看上一个状态的情况,如果我们是从上一个不换状态转移过来的,那么其必然有条件:(firstRow[i-1]>firstRow[i] & secondRow[i-1]<secondRow[i]),那么也就是每次的转移我们需要考虑四种情况。于是我们很容易得到方程:

    if (firstRow[i-1]>firstRow[i] && secondRow[i-1]<secondRow[i])
    	dp[i][0]=min(dp[i][0],dp[i-1][0]);
    if (secondRow[i-1]>firstRow[i] && firstRow[i-1]<secondRow[i])
    	dp[i][0]=min(dp[i][0],dp[i-1][1]);
    
    if (firstRow[i-1]>secondRow[i] && secondRow[i-1]<firstRow[i])
    	dp[i][1]=min(dp[i][1],dp[i-1][0]+1);
    if (secondRow[i-1]>secondRow[i] && firstRow[i-1]<firstRow[i])
    	dp[i][1]=min(dp[i][1],dp[i-1][1]+1);
    

    于是此题结束。

    以下是AC代码:

    const int mac=1e5+10;
    const int inf=1e9+10;
    int dp[mac][2];
    class Solution {
    public:
        /**
         * 计算最小交换次数
         * @param firstRow int整型vector 第一行的身高数据
         * @param secondRow int整型vector 第二行的身高数据
         * @return int整型
         */
        int arrange(vector<int>& firstRow, vector<int>& secondRow) {
            int n=firstRow.size();
            for (int i=0; i<=n; i++)
                dp[i][0]=dp[i][1]=inf;
            dp[0][0]=0; dp[0][1]=1;
            for (int i=1; i<n; i++){
                if (firstRow[i-1]>firstRow[i] && secondRow[i-1]<secondRow[i]) 
                    dp[i][0]=min(dp[i][0],dp[i-1][0]);
                if (secondRow[i-1]>firstRow[i] && firstRow[i-1]<secondRow[i]) 
                    dp[i][0]=min(dp[i][0],dp[i-1][1]);
                
                if (firstRow[i-1]>secondRow[i] && secondRow[i-1]<firstRow[i]) 
                    dp[i][1]=min(dp[i][1],dp[i-1][0]+1);
                if (secondRow[i-1]>secondRow[i] && firstRow[i-1]<firstRow[i]) 
                    dp[i][1]=min(dp[i][1],dp[i-1][1]+1);
            }
            int ans=min(dp[n-1][0],dp[n-1][1]);
            if (ans>=inf) return -1;
            return ans;
        }
    };
    
  • 相关阅读:
    软件工程结对第二次作业
    软件工程结对第一次作业
    软件工程第三次作业
    软件工程第二次作业
    软件工程第一次作业
    实验九:根据材料编程
    实验五:编写、调试具有多个段的程序
    实验4:[bx]和loop的使用
    《汇编语言》实验三——编程、编译、连接、跟踪
    《汇编语言》实验二——用机器指令和汇编指令编程
  • 原文地址:https://www.cnblogs.com/lonely-wind-/p/13512246.html
Copyright © 2020-2023  润新知