The reflected binary code, also known as Gray code after Frank Gray, is a binary numeral system where two successive values differ in only onebit (binary digit). The reflected binary code was originally designed to prevent spurious output from electromechanical switches. Today, Gray codes are widely used to facilitate error correction in digital communications such as digital terrestrial television and some cable TV systems. Now , you are given a binary number of length n including ‘0’ , ’1’ and ‘?’(? means that you can use either 0 or 1 to fill this position) and n integers(a1,a2,….,an) . A certain binary number corresponds to a gray code only. If the ith bit of this gray code is 1,you can get the point ai. Can you tell me how many points you can get at most? For instance, the binary number “00?0” may be “0000” or “0010”,and the corresponding gray code are “0000” or “0011”.You can choose “0000” getting nothing or “0011” getting the point a3 and a4.
The first line of the input contains the number of test cases T. Each test case begins with string with ‘0’,’1’ and ‘?’. The next line contains n (1<=n<=200000) integers (n is the length of the string). a1 a2 a3 … an (1<=ai<=1000)
For each test case, output “Case #x: ans”, in which x is the case number counted from one,’ans’ is the points you can get at most
2 00?0 1 2 4 8 ???? 1 2 4 8
Case #1: 12 Case #2: 15Hinthttps://en.wikipedia.org/wiki/Gray_code http://baike.baidu.com/view/358724.htm
题意:该题考查格雷码的性质,给你一个二进制串,带'?'的位置可以由你来决定填'1'还是'0',补充完整之后转换成格雷码表示,每一个位置都有一个权值a[i],只有格雷码为'1'的位可以加上权值,问你最终权值之和最大为多少。
依旧举个例子,加深理解,比如说样例1的二进制串00?0,'?'的地方可以是1,也可以是0,当为1时,转换成格雷码为0011,此时权值和为a[3]+a[4]=4+8=12;若你在'?'处填0的话,转换成格雷码之后是0000,那权值之和为0,所以权值之和最大为12。
解题思路:
刚开始的时候想的比较多,但是没有好的思路,总觉得左右互相影响的样子,但是从格雷码的性质来,就会发现此题足够水。先来介绍一下格雷码与二进制串是如何转换的。
然后举个例子,观察一下格雷码转换成二进制串的过程就可以解决此题。
如下例子对应的权值为5 7 4 6 3 1 8
所以x1和x2中有奇数个1,权值之和要尽可能大,所以在尽可能取1的情况下取权值大的位置。
如何取尽可能多的1呢,比如现在有奇数个连续的'?',而我们确定了有偶数个1,那我们只需进去权值最小的位置的1,就可以使总体和最大,比如我们知道了上面例子中x1,x2中只有一个1,那我们必定选权值大的为1,即x1=1,x2=0
按照此方法便可解出最终的解,若仍有疑问,欢迎提出,谢谢
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<queue> #include<math.h> #include<vector> #include<map> #include<set> #include<stdlib.h> #include<cmath> #include<string> #include<algorithm> #include<iostream> #define exp 1e-10 using namespace std; const int N = 200005; const int inf = 1000000000; char s[N]; int a[N],b[N]; int fun(int l,int r,int c,int Min) { if(c) if((r-l)%2) return b[r]-b[l]; else return b[r]-b[l]-Min; else if((r-l)%2) return b[r]-b[l]-Min; else return b[r]-b[l]; } int main() { int t,k,i,j,ans,Min,f=1; scanf("%d",&t); while(t--) { ans=0;Min=inf; scanf("%s",s+1); k=strlen(s+1);b[0]=0;s[0]='0'; for(i=1;i<=k;i++) { scanf("%d",&a[i]); b[i]=b[i-1]+a[i]; } for(i=0;i<k;i++) { if(s[i+1]!='?'&&s[i]!=s[i+1]) ans+=a[i+1]; //printf("%d*\n",ans); if(s[i+1]=='?') { for(j=i+1;j<=k&&s[j]=='?';j++) if(Min>a[j]) Min=a[j]; //printf("i=%d;j=%d;Min=%d;sum=%d;%d\n",i,j,Min,b[j]-b[i],(s[i]!=s[j]?1:0)); if(j>k) ans+=b[k]-b[i]; else { if(Min>a[j]) Min=a[j]; ans+=fun(i,j,i?(s[i]!=s[j]?1:0):s[j]-'0',Min); } i=j-1;Min=inf; } //printf("%d#\n",ans); } printf("Case #%d: %d\n",f++,ans); } }菜鸟成长记