HDU 5375(2015多校7)-Gray code(dp)

题目地址:HDU 5375

题意:给你一个二进制串,带’?’的位置可以由你来决定填’1’还是’0’,补充完整之后转换成格雷码表示,每一个位置都有一个权值a[i],只有格雷码为’1’的位可以加上权值,问你最终权值之和最大为多少。

思路:首先要明白二进制码和格雷码是如何转换的:

dp[i][0]表示第i位为0的时候的最大值,dp[i][1]表示第i位为1的时候的最大值。对于第i位的最大值由dp[i-1][0],dp[i-1][1]和当前权值a[i]得到。当前的位的二进制码有0,1,?三种情况,所以就分这三种情况讨论一下。

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <set>
#include <queue>
#include <stack>
#include <map>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
typedef __int64  LL;
const int inf=0x3f3f3f3f;
const double pi= acos(-1.0);
const double esp=1e-7;
const int Maxn=200010;
char str[Maxn];
int a[Maxn];
int dp[Maxn][2];
int main()
{
    int T,i,j;
    int Max;
    int icase=1;
    scanf("%d",&T);
    while(T--){
        scanf("%s",str);
        int len=strlen(str);
        memset(dp,-1,sizeof(dp));
        for(i=0;i<len;i++)
            scanf("%d",&a[i]);
        if(str[0]==‘?‘){
            dp[0][0]=0;
            dp[0][1]=a[0];
        }
        else if(str[0]==‘0‘){
            dp[0][0]=0;
        }
        else if(str[0]==‘1‘){
            dp[0][1]=a[0];
        }
        for(i=1;i<len;i++){
            if(str[i]==‘?‘){
              Max=-inf;
              if(dp[i-1][0]!=-1)
              Max=max(Max,dp[i-1][0]);
              if(dp[i-1][1]!=-1)
              Max=max(Max,dp[i-1][1]+a[i]);
              dp[i][0]=Max;
              Max=-inf;
              if(dp[i-1][0]!=-1)
              Max=max(Max,dp[i-1][0]+a[i]);
              if(dp[i-1][1]!=-1)
              Max=max(Max,dp[i-1][1]);
              dp[i][1]=Max;
            }
            else if(str[i]==‘0‘){
                Max=-inf;
                if(dp[i-1][0]!=-1)
                Max=max(Max,dp[i-1][0]);
                if(dp[i-1][1]!=-1)
                Max=max(Max,dp[i-1][1]+a[i]);
                dp[i][0]=Max;
            }
            else if(str[i]==‘1‘){
                Max=-inf;
                if(dp[i-1][0]!=-1)
                Max=max(Max,dp[i-1][0]+a[i]);
                if(dp[i-1][1]!=-1)
                Max=max(Max,dp[i-1][1]);
                dp[i][1]=Max;
            }
        }
        printf("Case #%d: %d\n",icase++,max(dp[len-1][0],dp[len-1][1]));
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-08 21:23:45

HDU 5375(2015多校7)-Gray code(dp)的相关文章

hdu 5288||2015多校联合第一场1001题

http://acm.hdu.edu.cn/showproblem.php?pid=5288 Problem Description OO has got a array A of size n ,defined a function f(l,r) represent the number of i (l<=i<=r) , that there's no j(l<=j<=r,j<>i) satisfy ai mod aj=0,now OO want to know ∑i

HDU 5347(2015多校5)-MZL&#39;s chemistry(打表)

题目地址HDU 5347 无脑流神题,自行脑补,百度大法好. #include <stdio.h> #include <math.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <sstream> #include <algorithm> #include <set> #include <queue> #

HDU 5344(2015多校5)-MZL&#39;s xor(水题)

题目地址:HDU 5344 题意:求所有(Ai+Aj)的异或值. 思路:可以发现(Ai+Aj)和(Aj+Ai)的异或值为0,所以最后只剩下(Ai+Ai). #include <stdio.h> #include <math.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <sstream> #include <algorithm>

HDU 5371(2015多校7)-Hotaru&#39;s problem(Manacher算法求回文串)

题目地址:HDU 5371 题意:给你一个具有n个元素的整数序列,问你是否存在这样一个子序列,该子序列分为三部分,第一部分与第三部分相同,第一部分与第二部分对称,如果存在求最长的符合这种条件的序列. 思路:用Manacher算法来处理回文串的长度,记录下以每一个-1(Manacher算法的插入)为中心的最大回文串的长度.然后从最大的开始穷举,只要p[i]-1即能得出以数字为中心的最大回文串的长度,然后找到右边对应的'-1',判断p[i]是不是大于所穷举的长度,如果当前的满足三段,那么就跳出,继续

HDU 5349(2015多校5)-MZL&#39;s simple problem(优先队列)

题目地址:HDU 5349 很水的优先队列就能搞好,只不过注意如果2操作结束后的队列为空,那么Max的值为-inf. #include <stdio.h> #include <math.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <sstream> #include <algorithm> #include <set&

HDOJ 5375 Gray code DP

标准格雷码的性质:二进制a1 a2 ... an,对应的格雷码为a1 (a1 xor a2) ... (an-1 xor an) 题目就可以转为O(n)的dp dp[i][j]表示二进制第i位为j时前i位对应最大分数. Gray code Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 298    Accepted Submissio

hdu 5375 Gray code dp

#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; const int N=200000+5; const int inf=1<<24; int dp[N][2],a[N]; char s[2*N]; int main() { int n,m,i,_; scanf("%d",&_); for(int k=1;k<=_;k+

HDU 5358(2015多校联合训练赛1006) First One (区间合并+常数优化)

HDU 5358 题意: 求∑?i=1?n??∑?j=i?n??(?log?2??S(i,j)?+1)?(i+j). 思路: S(i,j) < 10^10 < 2^34,所以log2(S)+1的值只可能在1~35之间.由于log变化缓慢的函数特性,我们可以S(i,n)分作多个相同log值的区间来计算,用pos[i][j]预处理记录每个以i为起点,log(s)值为j的区间的右边界,即可优化至nlogn的复杂度. 主要是写起来比较难一些,一些细节比较纠结,一定思路理清后再写. ps.此题卡常数毫无

HDU 5323(2015多校3)-Solve this interesting problem(dfs+剪枝)

题目地址:HDU 5323 题意:给一个l,r,表示区间[l,r],问是否存在区间为[0,n]的线段树的节点区间为[l,r],如果有求最小的n,如果没有输出-1. 思路:因为L/(R-L+1)<=2015,按照线段树的性质每次分区间序号扩大两倍,所以可以得出差不多有22层,所以用爆搜就可以,由上把[l,r]区间不断扩张,直到满足l==0为止.顺便剪剪枝. #include <stdio.h> #include <math.h> #include <string.h>