D - Shift and Flip
Time limit
配点 : 1000 点
問題文
0 と 1 からなる同じ長さの二つの文字列 A=A1A2…An と B=B1B2…Bn があります。
あなたは、以下の操作を任意の順序で何度でも行って A を変化させることができます。
- A を一文字左にシフトする(すなわち、A=A1A2…An として A を A2A3…AnA1 に置き換える)。
- A を一文字右にシフトする(すなわち、A=A1A2…An として A を AnA1A2…An−1 に置き換える)。
- Bi=1 であるような i をいずれか一つ選び、Ai を反転する(すなわち、Ai=1−Ai とする)。
あなたの目標は文字列 A,B を一致させることです。
これに必要な最小の操作回数を出力してください。ただし、これが不可能である場合は −1 と出力してください。
制約
- 1≤|A|=|B|≤2,000
- A,B は 0 と 1 からなる。
入力
入力は以下の形式で標準入力から与えられる。
A B
出力
文字列 A,B を一致させるために必要な最小の操作回数を出力せよ。ただし、これが不可能である場合は −1 と出力せよ。
入力例 1
1010 1100
出力例 1
3
目標を達成する最短の操作列を一つ示します。
- A1 を反転: A=0010
- A を左にシフト: A=0100
- A1 を再度反転: A=1100
入力例 2
1 0
出力例 2
-1
A の唯一のビットを反転させる方法はありません。
入力例 3
11010 10001
出力例 3
4
目標を達成する最短の操作列を一つ示します。
- A を右にシフト: A=01101
- A5 を反転: A=01100
- A を左にシフト: A=11000
- A を再度左にシフト: A=10001
入力例 4
0100100 1111111
出力例 4
5
A1, A3, A4, A6, A7 を任意の順序で反転すればよいです。
Score : 1000 points
Problem Statement
You have two strings A=A1A2…An and B=B1B2…Bn of the same length consisting of 0 and 1.
You can transform A using the following operations in any order and as many times as you want:
- Shift A by one character to the left (i.e., if A=A1A2…An, replace A with A2A3…AnA1).
- Shift A by one character to the right (i.e., if A=A1A2…An, replace A with AnA1A2…An−1).
- Choose any i such that Bi=1. Flip Ai (i.e., set Ai=1−Ai).
You goal is to make strings A and B equal.
Print the smallest number of operations required to achieve this, or −1 if the goal is unreachable.
Constraints
- 1≤|A|=|B|≤2,000
- A and B consist of 0 and 1.
Input
Input is given from Standard Input in the following format:
A B
Output
Print the smallest number of operations required to make strings A and B equal, or −1 if the goal is unreachable.
Sample Input 1
1010 1100
Sample Output 1
3
Here is one fastest way to achieve the goal:
- Flip A1: A=0010
- Shift A to the left: A=0100
- Flip A1 again: A=1100
Sample Input 2
1 0
Sample Output 2
-1
There is no way to flip the only bit in A.
Sample Input 3
11010 10001
Sample Output 3
4
Here is one fastest way to achieve the goal:
- Shift A to the right: A=01101
- Flip A5: A=01100
- Shift A to the left: A=11000
- Shift A to the left again: A=10001
Sample Input 4
0100100 1111111
Sample Output 4
5
Flip A1, A3, A4, A6 and A7 in any order.
整个过程为序列向左、向右移动,以及单独修改某一个位置。故在此过程中存在最左移动的值,最右移动的值,以及最终的位移量。
显然根据单独修改的条件,对B为全是0的串需要单独判断。
之后枚举d(分别为向左、向右移动0——len-1)每一次计算当下的最优L、R(最左、最右移动的值),该值需满足所有与对应最终位置的Bi不同的Ai要经过过至少1次“1”。
为此可以简单的dp一下,即可在O(n)时间内求出。故整体时间复杂度为O(n^2)
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <vector> 5 #include <set> 6 #include <map> 7 #include <string> 8 #include <cstring> 9 #include <stack> 10 #include <queue> 11 #include <cmath> 12 #include <ctime> 13 #include<bitset> 14 #include <utility> 15 using namespace std; 16 #define rank rankk 17 #define mp make_pair 18 #define pb push_back 19 #define xo(a,b) ((b)&1?(a):0) 20 //#define LL ll 21 typedef unsigned long long ull; 22 typedef pair<int,int> pii; 23 typedef long long ll; 24 typedef pair<ll,int> pli; 25 const int INF=0x3f3f3f3f; 26 const ll INFF=0x3f3f3f3f3f3f3f3fll; 27 //#define xs1 xs 28 //#define xs2 x 29 //const ll M=1e9+7; 30 //const ll maxn=2e5+7; 31 //const int MAXN=1005; 32 const int MAX=2e3+5; 33 const int MAX_N=MAX; 34 //const int N=55; 35 const ll MOD=1000000007; 36 const long double pi=acos(-1.0); 37 //const double eps=0.00000001; 38 int gcd(int a,int b){return b?gcd(b,a%b):a;} 39 template<typename T>inline T abs(T a) {return a>0?a:-a;} 40 template<class T> inline 41 void read(T& num) { 42 bool start=false,neg=false; 43 char c; 44 num=0; 45 while((c=getchar())!=EOF) { 46 if(c=='-') start=neg=true; 47 else if(c>='0' && c<='9') { 48 start=true; 49 num=num*10+c-'0'; 50 } else if(start) break; 51 } 52 if(neg) num=-num; 53 } 54 inline ll powMM(ll a,ll b,ll M){ 55 ll ret=1; 56 a%=M; 57 // b%=M; 58 while (b){ 59 if (b&1) ret=ret*a%M; 60 b>>=1; 61 a=a*a%M; 62 } 63 return ret; 64 } 65 void open() 66 { 67 freopen("1009.in","r",stdin); 68 freopen("out.txt","w",stdout); 69 } 70 char a[MAX],b[MAX]; 71 int l[MAX],r[MAX],len,an,cnt,tem; 72 int x[MAX];//在某个x时最大的y 73 int main() 74 { 75 scanf("%s%s",a,b);an=INF; 76 len=strlen(a); 77 bool st1,st2;st1=st2=true; 78 for(int i=0;i<len&&st1;i++)if(a[i]=='1')st1=false; 79 for(int i=0;i<len&&st2;i++)if(b[i]=='1')st2=false; 80 if(st2) 81 { 82 if(st1)printf("0 ");else printf("-1 ");return 0; 83 } 84 for(int i=0;i<len;i++) 85 { 86 int j=0; 87 for(;b[(i+j)%len]!='1';)++j; 88 r[i]=j; 89 } 90 for(int i=0;i<len;i++) 91 { 92 int j=0;for(;b[(i-j+len)%len]!='1';)++j; 93 l[i]=j; 94 } 95 for(int d=0;d<len;d++)//枚举d 96 { 97 cnt=0;tem=INF;memset(x,0,sizeof(x)); 98 //最终向右移动 99 for(int i=0;i<len;i++) 100 { 101 if(a[i]!=b[(i+d)%len]){ 102 ++cnt; 103 if(r[i]<=d)continue;//不需要加 104 x[l[i]]=max(x[l[i]],r[(i+d)%len]); 105 } 106 } 107 for(int i=len-1;i>=0;i--){ 108 x[i]=max(x[i],x[i+1]); 109 tem=min(x[i+1]+i,tem); 110 } 111 an=min(an,2*tem+d+cnt); 112 //最终向左移动 113 cnt=0;tem=INF;memset(x,0,sizeof(x)); 114 for(int i=0;i<len;i++) 115 { 116 if(a[i]!=b[(i-d+len)%len]) 117 { 118 ++cnt; 119 if(l[i]<=d)continue;//不需要加 120 x[l[(i-d+len)%len]]=max(x[l[(i-d+len)%len]],r[i]); 121 } 122 } 123 for(int i=len-1;i>=0;i--) 124 { 125 x[i]=max(x[i],x[i+1]); 126 tem=min(x[i+1]+i,tem); 127 } 128 an=min(an,2*tem+d+cnt); 129 } 130 printf("%d ",an); 131 return 0; 132 }