HDU 5375 Gray code

分析:给你一串二进制码,其中?可以表示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;
  }


你可能感兴趣的:(ACM)