(dp)AtCoder Grand Contest 019 D - Shift and Flip

D - Shift and Flip


Time limit時間制限 : 2sec / Memory limitメモリ制限 : 256MB

配点 : 1000

問題文

01 からなる同じ長さの二つの文字列 A=A1A2AnB=B1B2Bn があります。

あなたは、以下の操作を任意の順序で何度でも行って A を変化させることができます。

  • A を一文字左にシフトする(すなわち、A=A1A2An として AA2A3AnA1 に置き換える)。
  • A を一文字右にシフトする(すなわち、A=A1A2An として AAnA1A2An−1 に置き換える)。
  • Bi=1 であるような i をいずれか一つ選び、Ai を反転する(すなわち、Ai=1−Ai とする)。

あなたの目標は文字列 A,B を一致させることです。

これに必要な最小の操作回数を出力してください。ただし、これが不可能である場合は −1 と出力してください。

制約

  • 1≤|A|=|B|≤2,000
  • A,B01 からなる。

入力

入力は以下の形式で標準入力から与えられる。

A
B

出力

文字列 A,B を一致させるために必要な最小の操作回数を出力せよ。ただし、これが不可能である場合は −1 と出力せよ。


入力例 1

Copy
1010
1100

出力例 1

Copy
3

目標を達成する最短の操作列を一つ示します。

  • A1 を反転: A=0010
  • A を左にシフト: A=0100
  • A1 を再度反転: A=1100

入力例 2

Copy
1
0

出力例 2

Copy
-1

A の唯一のビットを反転させる方法はありません。


入力例 3

Copy
11010
10001

出力例 3

Copy
4

目標を達成する最短の操作列を一つ示します。

  • A を右にシフト: A=01101
  • A5 を反転: A=01100
  • A を左にシフト: A=11000
  • A を再度左にシフト: A=10001

入力例 4

Copy
0100100
1111111

出力例 4

Copy
5

A1, A3, A4, A6, A7 を任意の順序で反転すればよいです。

Score : 1000 points

Problem Statement

You have two strings A=A1A2An and B=B1B2Bn 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=A1A2An, replace A with A2A3AnA1).
  • Shift A by one character to the right (i.e., if A=A1A2An, replace A with AnA1A2An−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

Copy
1010
1100

Sample Output 1

Copy
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

Copy
1
0

Sample Output 2

Copy
-1

There is no way to flip the only bit in A.


Sample Input 3

Copy
11010
10001

Sample Output 3

Copy
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

Copy
0100100
1111111

Sample Output 4

Copy
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\n");else printf("-1\n");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\n",an);
131     return 0;
132 }

 

posted @ 2017-08-30 22:29  perplex  阅读(137)  评论(0编辑  收藏  举报