题目来源:http://codeforces.com/gym/100712
反转(开关问题)的变式。
要先从0~9枚举最终状态下的所有数字。然后从大到小验证所选分段是否可行。
假设所选的段长为x,因为最左侧的那一位只能属于[0,x]这一段,因此便可从第一位开始确定,依次向右一位一位进行操作,如果可以将全部位置上的数字均转变为所要的数字,则x可行。
代码:
#include <bits/stdc++.h>
using namespace std;
char s[1001];
int a[1001];
int n;
int b[1001];
bool can(int x)
{
for(int i=1;i<=n;++i)b[i]=a[i];
for(int k=0;k<=9;++k)
{
bool ok=1;
for(int i=1;i<=n-x+1;++i)
{
if(b[i]!=k)
{
if(b[i]<k)
{
int t=k-b[i];
b[i]=k;
for(int j=1;j<x;++j)
b[i+j]=(b[i+j]+t)%10;
} else
{
int t=k+10-b[i];
b[i]=k;
for(int j=1;j<x;++j)
b[i+j]=(b[i+j]+t)%10;
}
}
}
for(int i=1;i<=n;++i)
if(b[i]!=k)
{
ok=0;
break;
}
if(ok)return 1;
}
return 0;
}
int main()
{
int _;scanf("%d",&_);
while(_--)
{
memset(s,0,sizeof(s));
scanf("%s",s);
n=strlen(s);
for(int i=0;i<n;++i)
a[i+1]=s[i]-'0';
for(int i=n;i>=1;--i)
if(can(i))
{
printf("%d\n",i);
break;
}
}
return 0;
}
/*
3
04
651
0552
*/