2015 Multi-University Training Contest 7 1007(DP)

Gray code

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 208    Accepted Submission(s): 117


php

Problem Description
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.
 

 

Input
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)
 

 

Output
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
 

 

Sample Input
2
00?0
1 2 4 8
????
1 2 4 8
 

 

Sample Output
Case #1: 12
Case #2: 15
Hint
https://en.wikipedia.org/wiki/Gray_code
http://baike.baidu.com/view/358724.htm
 
 
 
Source
 
題意:給出一串由 '0'  '1'   '?' 組成的二進制字符串,其中'?'表示多是0也多是1,將這個二進制穿換成格雷碼,而後在格雷碼相應下標有一個權值,爲1則加上該權值,爲0表示不加,問由二進制轉換成格雷碼以後權值相加最大值是多少?
分析:
用dp作這道題
dp[i][0]表示二進制下標在下標爲 i 處取0轉換成格雷碼後的權值
dp[i][1]表示二進制下標在下標爲 i 處取0轉換成格雷碼後的權值
 
那麼再分狀況討論,因爲二進制轉換成格雷碼的一種方法是
從最右邊一位起,依次將每一位與左邊一位異或(XOR),做爲對應格雷碼該位的值,最左邊一位不變(至關於左邊是0)
 
再分狀況討論相鄰兩位的關係
 
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<string>
#include<iostream>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<map>
#include<stdlib.h>
#include<algorithm>
#define LL __int64
using namespace std;
const int MAXN=200000+5;
int dp[MAXN][2],a[MAXN];
char str[MAXN];
int kase,len;
int main()
{
    //freopen("in.txt","r",stdin);
    int Case=0;
    scanf("%d",&kase);
    while(kase--)
    {
        memset(str,0,sizeof(str));
        memset(a,0,sizeof(a));
        memset(dp,0,sizeof(dp));

        scanf("%s",str);
        len=strlen(str);
        for(int i=0;i<len;i++) scanf("%d",&a[i]);

        dp[0][0]=0;
        dp[0][1]=a[0];
        for(int i=1;i<len;i++)
        {
            if(str[i]=='?')
            {
                if(str[i-1]=='?')
                {
                    dp[i][0]=max(dp[i-1][0],dp[i-1][1]+a[i]);//假設當前位爲0,前一位爲0則轉換後仍是0,前一位爲1則轉換後爲1
                    dp[i][1]=max(dp[i-1][0]+a[i],dp[i-1][1]);
                }
                else
                {
                    dp[i][0]=dp[i-1][str[i-1]-'0']+a[i]*(0^(str[i-1]-'0'));
                    dp[i][1]=dp[i-1][str[i-1]-'0']+a[i]*(1^(str[i-1]-'0'));
                }
            }
            else
            {
                if(str[i-1]=='?')
                    dp[i][str[i]-'0']=max(dp[i-1][0]+a[i]*(0^(str[i]-'0')),dp[i-1][1]+a[i]*(1^(str[i]-'0')));
                else
                    dp[i][str[i]-'0']=dp[i-1][str[i-1]-'0']+a[i]*((str[i-1]-'0')^(str[i]-'0'));//注意運算符的優先級
            }
        }
        printf("Case #%d: ",++Case);
        if(str[len-1]=='?') printf("%d\n",max(dp[len-1][0],dp[len-1][1]));
        else printf("%d\n",dp[len-1][str[len-1]-'0']);
    }
    return 0;
}
View Code
相關文章
相關標籤/搜索