問題の意味:三つの値与えられた(nは1)は、3つの動作シーケンスのシーケンス番号値は、第一の配列は、n-1の接頭辞であるように、第3のシーケンスは、1〜2の接尾辞であります他の値の第2シーケンス。シフトの最小数を確認して下さい。
分析:
例を置くこと。
- 13123(これは、それぞれ1,2,3,4,5値のセットです):私たちは、各シーケンスの値が属する書きしてみてください。
問題は、全体のシーケンスのプレフィックスが1フル接尾辞である、(一つだけ1,2,3変更)最小数の値を変更することにより、配列あなたの一方のみ三つの値1、2を変更することです3、他のパート2。
$ [I]とDP [j]はiは、タイトルの意味ビットの前に変更数が満たされている(すなわち、J-I群で)jへ$ iビットの値を示します。転送は、コードのコメントを参照してください。
コード:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MA=2e5+5;
int a[5],vis[MA],dp[MA][5];
int main()
{
int n=0;
scanf("%d%d%d",&a[0],&a[1],&a[2]);
for(int k=0;k<=2;++k){
n=a[k];
int x;
for(int i=0;i<n;++i){
scanf("%d",&x);
vis[x]=k+1; //构造新序列
}
}
n=a[0]+a[1]+a[2];
for(int i=1;i<=n;++i){
if(vis[i]==1){
dp[i][1]=dp[i-1][1];
dp[i][2]=min(dp[i-1][2]+1,dp[i-1][1]+1);
dp[i][3]=min(dp[i-1][1]+1,min(dp[i-1][2]+1,dp[i-1][3]+1));
}
else if(vis[i]==2){
dp[i][1]=dp[i-1][1]+1;
dp[i][2]=min(dp[i-1][1],dp[i-1][2]);
dp[i][3]=min(dp[i-1][1]+1,min(dp[i-1][2]+1,dp[i-1][3]+1));
}
else if(vis[i]==3){
dp[i][1]=dp[i-1][1]+1;
dp[i][2]=min(dp[i-1][1]+1,dp[i-1][2]+1);
dp[i][3]=min(dp[i-1][1],min(dp[i-1][2],dp[i-1][3]));
}
}
printf("%d\n",min(dp[n][1],min(dp[n][2],dp[n][3])));
return 0;
}