题目链接
https://agc019.contest.atcoder.jp/tasks/agc019_d
题意简述
有两个0/1串,可以对串执行以下操作:
- 向左旋转串,变成。
- 向右旋转串,变成。
- 当时反转位置,0变1,1变0。
求最少多少次操作后串相同。
题解
枚举串向右旋转了多少次,向左旋转同理。显然可以得出旋转后的位置。假设旋转过程中这些位置都没有对上一个的位置,那么要么开始向左旋转一个位置然后转回来,要么转到目标位置后向右旋转一个位置然后转回去。对于每个上述位置,如果开始向左旋转的长度时就必须向右旋转,因此可以处理出来然后前缀和一遍求出向左旋转对应需要向右旋转的长度。
代码
#include <cstdio>
#include <cstring>
#include <algorithm>
int read()
{
  int x=0,f=1;
  char ch=getchar();
  while((ch<'0')||(ch>'9'))
    {
      if(ch=='-')
        {
          f=-f;
        }
      ch=getchar();
    }
  while((ch>='0')&&(ch<='9'))
    {
      x=x*10+ch-'0';
      ch=getchar();
    }
  return 0;
}
const int maxn=2000;
const int inf=0x3f3f3f3f;
int n,ans,a[maxn+10],b[maxn+10],sum[maxn+10],nxt[maxn+10],past[maxn+10],f[maxn+10];
char tmp[maxn+10];
inline int trans(int i,int x)
{
  if(i+x>n)
    {
      return i+x-n;
    }
  return i+x;
}
inline int getsum(int l,int r)
{
  if(r>=l)
    {
      return sum[r]-sum[l-1];
    }
  return sum[n]-sum[l-1]+sum[r];
}
int solve()
{
  for(int i=1; i<=n; ++i)
    {
      sum[i]=sum[i-1]+b[i];
    }
  for(int i=1; i<=n; ++i)
    {
      for(int j=0; j<n; ++j)
        {
          if(getsum(i,trans(i,j)))
            {
              nxt[i]=j;
              break;
            }
        }
      for(int j=0; j<n; ++j)
        {
          if(getsum(trans(i,n-j),i))
            {
              past[i]=j;
              break;
            }
        }
    }
  for(int i=0; i<n; ++i)
    {
      memset(f,0,sizeof f);
      int cnt=0;
      for(int j=1; j<=n; ++j)
        {
          if(a[j]!=b[trans(j,i)])
            {
              ++cnt;
              if(nxt[j]-i>0)
                {
                  f[past[j]-1]=std::max(f[past[j]-1],nxt[j]-i);
                }
            }
        }
      for(int j=n-1; j>=0; --j)
        {
          f[j]=std::max(f[j],f[j+1]);
          ans=std::min(ans,(f[j]+j)*2+i+cnt);
        }
    }
  return 0;
}
int main()
{
  scanf("%s",tmp+1);
  n=strlen(tmp+1);
  for(int i=1; i<=n; ++i)
    {
      a[i]=tmp[i]-'0';
    }
  scanf("%s",tmp+1);
  for(int i=1; i<=n; ++i)
    {
      b[i]=tmp[i]-'0';
    }
  int flag=0;
  for(int i=1; i<=n; ++i)
    {
      if(b[i])
        {
          flag=1;
          break;
        }
    }
  if(!flag)
    {
      for(int i=1; i<=n; ++i)
        {
          if(a[i])
            {
              flag=1;
              break;
            }
        }
      puts(flag?"-1":"0");
      return 0;
    }
  ans=inf;
  solve();
  std::reverse(a+1,a+n+1);
  std::reverse(b+1,b+n+1);
  solve();
  printf("%d\n",ans);
  return 0;
}
 
                    
                     
                    
                 
                    
                 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号