原题链接:https://leetcode-cn.com/problems/minimum-swaps-to-make-sequences-increasing/
动态规划
dp[0]表示若当前位置不做交换时的次数
dp[1]表示若当前位置做交换时的次数
同时初始化dp[0]=0,dp[1]=1,表示第一步要么换要么不换。然后分析一下题目的状态,共有四种状态:
1、A[i-1]<A[i] && B[i-1]< B[i]
2、A[i-1]>=A[i] || B[i-1]>=B[i]
3、A[i-1]>=B[i] || B[i-1]>=A[i]
4、A[i-1]<B[i] && B[i-1]<A[i]
然后对每个状态考虑如何状态转移,backup保存dp上个位置的状态。
1、 正确的情况,不一定做改变,如果前一个交换了,这个可以交换或不交换;如果前一个不交换,这个也可以交换或不交换。
dp[0]=backup[0]||backup[1];
dp[1]=backup[0]+1||backup[1]+1;
2、 必须做改变,如果前一个交换了,则这个不用交换;如果前一个没交换,则这个交换。
dp[0]=backup[1];
dp[1]=backup[0]+1;
3、 不一定做改变,但是如果前一个交换了,这个也必须交换;如果前一个没有交换,则这个也不用交换。
dp[0]=backup[0];
dp[1]=backup[1]+1;
4、不一定做改变,如果前一个交换了,这个可以交换或不交换;如果前一个不交换,这个也可以交换或不交换,同1的情形是一样的。
dp[0]=backup[0]||backup[1];
dp[1]=backup[0]+1||backup[1]+1;
值得注意的是,2和3是互斥的,同时只有一个可能发生;而1和4不是互斥的,可能同时发生,所以将两种情况整合在一起,用贪心算法,既然可做可不做,那就不做,取前一步的最小值min(backup[0],backup[1]),于是dp[0]=min,dp[1]=min+1。
int minSwap(vector<int>& A, vector<int>& B) {
int len=A.size();
vector<int> dp{0,1};
vector<int> backup;
for(int i=1;i<len;i++){
backup=dp;
if(A[i-1]>=A[i]||B[i-1]>=B[i]){
dp[0]=backup[1];
dp[1]=backup[0]+1;
}else if(A[i-1]>=B[i]||B[i-1]>=A[i]){
dp[0]=backup[0];
dp[1]=backup[1]+1;
}else{
dp[0]=min(backup[0],backup[1]);
dp[1]=min(backup[0],backup[1])+1;
}
}
return min(dp[0],dp[1]);
}