分析:给你一串二进制码,其中?可以表示0或1,让你将二进制码转化为格雷码,转化后的格雷码上数位为1的可以加上改为的分数,让你求最大分数。二进制码转化为格雷码比较简单:a^(a>>1),就是二进制位除第一位外每一位都和前一位异或,得到的结果就是该位格雷码的数字,其中第一位不变。如果二进制的一部分是0????1、1??0、0?????0、1???1,就是偶数个连续问号且两头异,或是奇数个连续?且两头同,二进制都存在010101....或1010101...的情况,这样转化为格雷码就是0111....或11111111.....(头一位不变),否则最好的情况除头一位不变外,其他的连续?和最后一个?后的字符转化后都会存在一个0。
# include <stdio.h>
# include <string.h>
int main()
{
int i,n,t,k,ans,cas=1,a[200005],min;
char s[200005],c;
scanf("%d",&t);
while(t--)
{
scanf("%s",s+1);
n=strlen(s+1);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
s[0]='0';a[0]=0;ans=0;
for(i=1;i<=n;i++)
{
if(s[i]!='?'&&s[i-1]!='?')
{
if(s[i]!=s[i-1])
ans+=a[i];
}
else if(s[i]=='?'&&s[i-1]!='?')
{
c=s[i-1];
for(min=a[i],k=0;i<=n&&s[i]=='?';i++,k++)
{
ans+=a[i];
if(a[i]<min)
min=a[i];
}
ans+=a[i];
if(a[i]<min)
min=a[i];
if(k%2==0&&c==s[i])
ans-=min;
else if(k%2==1&&c!=s[i])
ans-=min;
}
}
printf("Case #%d: %d\n",cas++,ans);
}
return 0;
}