zoukankan      html  css  js  c++  java
  • HDU 5375——Gray code——————【dp||讨论】

    Gray code

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


    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
     
     
    题目大意:给出一个字符串表示二进制,只含有1,0,?这三种字符。?可以转化成1或者0。下面有字符串长度个值,分别表示该位的价值。让你把二进制串转化成格雷码,转化后的格雷码中是1的位置,可以获得对应下面的价值。问你最大能获得的价值是多少。
     
    解题思路1:dp[i][j]表示二进制第i位为j时的最大价值。那么当str[i]为’1'时,dp[i][1]=max(dp[i-1][0]+a[i],dp[i-1][1])。当str[i]为'0'时,dp[i][0]=max(dp[i-1][0],dp[i-1][1]+a[i])。当str[i]为’?'时,dp[i][0]=max(dp[i-1][1]+a[i],dp[i-1][0]),dp[i][1]=max(dp[i-1][0]+a[i],dp[i-1][1])。同时应该注意初始化。
     
    解题思路2:当时比赛没想到dp。跟对友讨论出来了一种方法,比较麻烦。逆向进行,考虑问号两边的数字是否相同,同时考虑问号个数的奇偶,还有就是要边界处理。比较繁琐。
     
    dp:
    #include<bits/stdc++.h>
    using namespace std;
    #define max(a,b) ((a)>(b)?(a):(b))
    const int maxn=1e5+200;
    const int INF=0x3f3f3f3f;
    int dp[2*maxn][2];
    int a[2*maxn];
    char str[2*maxn];
    int main(){
        int t,cnt=0;
        scanf("%d",&t);
        while(t--){
            scanf("%s",str+1);
            int len=strlen(str+1);
            for(int i=1;i<=len;i++){
                scanf("%d",&a[i]);
                dp[i][1]=dp[i][0]=-INF;
            }
            if(str[1]=='0'){
                dp[1][0]=0;
            }else if(str[1]=='1'){
                dp[1][1]=a[1];
            }else{
                dp[1][0]=0;
                dp[1][1]=a[1];
            }
            for(int i=2;i<=len;i++){
                if(str[i]=='0'){
                    dp[i][0]=max(dp[i-1][0],dp[i-1][1]+a[i]);
                }else if(str[i]=='1'){
                    dp[i][1]=max(dp[i-1][0]+a[i],dp[i-1][1]);
                }else {
                    dp[i][1]=max(dp[i-1][0]+a[i],dp[i-1][1]);
                    dp[i][0]=max(dp[i-1][1]+a[i],dp[i-1][0]);
                }
            }
            printf("Case #%d: %d
    ",++cnt,max(dp[len][1],dp[len][0]));
        }
        return 0;
    }
    

      

    讨论:

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    const int maxn=1e6+200;
    const int INF=0x3f3f3f3f;
    char str[2*maxn];
    int a[maxn*2];
    int main(){
        int t,cnt=0;
        scanf("%d",&t);
        while(t--){
            scanf("%s",str);
            int len=strlen(str);
            for(int i=0;i<len;i++)
                scanf("%d",&a[i]);
            int sum=0,pos=len,flag=-1;
            int i;
            for(i=len-1;i>=0;i--){  //逆序处理
                if(str[i]=='0'){
                    if(flag==1){    //如果右边有1
                        sum+=a[pos];
                    }
                    flag=0; //表示当前是0
                    pos=i;
                    continue;
                }else if(str[i]=='1'){
                    if(flag==0){
                        sum+=a[pos];
                    }
                    flag=1;
                    pos=i;
                    continue;
                }else{  //是问号
                    int num=0,sumv,minv;
                    if(flag!=-1){
                        minv=a[pos],sumv=a[pos];
                    }
                    else {
                        minv=INF,sumv=0;
                    }
                    int j;
                    for(j=i;j>=0;j--){
                        if(str[j]=='0'){
                            if(flag==1){
                                if(num%2==1){   //如果问号两边不同,且中间的问号为奇数个,舍弃这段中的最小值
                                    sum+=(sumv-minv);
                                }else {
                                    sum+=sumv;
                                }
                            }else if(flag==0){      
                                if(num%2==1){   //如果两边相同,且中间为奇数个,加上这段所有值      
                                    sum+=sumv;
                                }else{
                                    sum+=(sumv-minv);
                                }
    
                            }else{
                                sum+=sumv;
                            }
                            flag=-1;
                            pos=len;
                            i=j+1;
                            break;
                        }else if(str[j]=='1'){
                            if(flag==0){
                                if(num%2==1){
                                    sum+=(sumv-minv);
                                }else{
                                    sum+=sumv;
                                }
                            }else if(flag==1){
                                if(num%2==0){
                                    sum+=(sumv-minv);
                                }else{
                                    sum+=sumv;
                                }
                            }else{
                                sum+=sumv;
                            }
                            flag=-1;
                            pos=len;
                            i=j+1;
                            break;
                        }else {
                            num++;
                            sumv+=a[j];
                            if(minv>a[j]){
                                minv=a[j];
                            }
                        }
                    }
                    if(j==-1){  //边界处理,比较恶心
                       i=0;
                        if(flag==-1 )
                            sum+=sumv;
                        else if (flag==1){
                            if(num%2==0){
                                sum+= sumv;
                            }
                            else sum+=(sumv-minv);
                        }else {
                            if(num%2==1){
                                sum+=sumv;
                            }else{
                                sum+=(sumv-minv);
                            }
                        }
                    }
                }
            }
            if(str[0]=='1'&&i==-1){ //字串第一位
                sum+=a[0];
            }
            printf("Case #%d: %d
    ",++cnt,sum);
        }
        return 0;
    }
    

      

  • 相关阅读:
    JS代码和网页的混用
    猫扑论坛遭遇黑客挂马
    安全专家解析黑客攻击网银四大手段
    网页分析利器:IEDevToolBar
    2009年世界顶级杀毒软件排行榜
    英特尔遭遇CPU级RootKit,目前无药可医
    Linq联表查询
    从客户端中检测到有潜在危险的 Request.Form 值。
    MVC Cookie的使用
    TimSpan比较时间差
  • 原文地址:https://www.cnblogs.com/chengsheng/p/4724853.html
Copyright © 2011-2022 走看看