801. 使序列递增的最小交换次数(状态机dp)

发布时间 2023-08-26 13:12:13作者: 深渊之巅

 

dp的本质就是图论

状态机dp就是包含多个待选状态,个人感觉就是分层图,每一层是一个状态,不同状态之间有可以相互转化的方法。通过状态和状态之间的关系,来实现状态转移。

本题f[i][j]表示只从前i项中选,f[i][0]表示第i项不进行交换,f[i][1]表示第i项进行交换,达到严格递增情况下所需要的最小操作次数。

状态转移:

  若nums1[i] > nums1[i - 1] && nums2[i] > nums2[i - 1]则可以将两个数字一起交换,要么一起交换,要么一起都不换,有 f[i][0] = f[i - 1][0], f[i][1] = f[i - 1][1] + 1;

  若nums1[i] > nums2[i - 1] && nums2[i] > nums1[i - 1]则可以交换第i项或第i - 1项, 有f[i][0] = min(f[i][0], f[i - 1][1]), f[i][1] = min(f[i][1], f[i - 1][0] + 1);

class Solution {
public:
    int minSwap(vector<int>& nums1, vector<int>& nums2) {
        int n = nums1.size();
        vector<vector<int>> f(n, vector<int>(2));
        f[0][0] = 0, f[0][1] = 1;
        for(int i = 1; i < n; i ++ ) f[i][0] = f[i][1] = 0x3f3f3f3f;

        for(int i = 1; i < n; i ++ ) {
            if(nums1[i - 1] < nums1[i] && nums2[i - 1] < nums2[i]) {
                f[i][0] = f[i - 1][0];
                f[i][1] = f[i - 1][1] + 1;
            }
            if(nums1[i] > nums2[i - 1] && nums2[i] > nums1[i - 1]) {
                f[i][0] = min(f[i][0], f[i - 1][1]);
                f[i][1] = min(f[i][1], f[i - 1][0] + 1);
            }
        }

        return min(f[n - 1][0], f[n - 1][1]);
    }
};