zoukankan      html  css  js  c++  java
  • 【简单dp+模拟】hdu-5375(2015多校#7-1007)

    给你一个二进制数,,每一位有一个权值,让你转格雷码,求所对应格雷码位为1的权值的和;二进制位中的某些位为?,你需要给这些问号赋值使得到的和最大。

    首先你得知道二进制转格雷码的规则,即格雷码位为【二进制位与左边前一位的异或值】,格雷码首位为二进制首位;

    因为格雷码首位为二进制首位,那么可以视二进制首位的左边前一位是0;

    然后你就可以分情况模拟了:

    1、连续数字的情况直接计算即可;

    2、连续问号的情况需要dp一下:dp[k][j]表示第k个问号是j时,得到的最大和,那么dp[k][j] = max(dp[k-1][!j]+w[i], dp[k-1][j]);首尾的细节处要处理好;

      这里也可以不用dp直接模拟求,需要分一下问号数的奇偶性,比较复杂不再讨论了;

    附代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<string>
     6 #include<queue>
     7 using namespace std;
     8 typedef long long ll;
     9 const int maxn = 200005;
    10 char bin[maxn];
    11 int w[maxn];
    12 int dp[maxn][3];
    13 
    14 int main()
    15 {
    16     int T;
    17     scanf("%d", &T);
    18     for(int kase = 1; kase <= T; kase++)
    19     {
    20         scanf("%s", bin+1);
    21         bin[0] = '0';
    22         int len = strlen(bin+1);
    23         for(int i = 1; i<= len; i++)
    24             scanf("%d", &w[i]);
    25 
    26         int ans = 0, i = len;
    27         while(i >= 1)
    28         {
    29             if(bin[i] != '?')
    30             {
    31                 if(bin[i-1] == '?') // X????1 连问号且尾接数字,dp[i][j]为(从右向左问号的)第i位为j时最大值:dp[i][j] = (dp[i][!j]+w[i] , dp[i][j]);
    32                 {
    33                     int pos = 1; //注意结尾的数字要单独考虑,结尾(bin[i])是1,则dp[1][0]=w[i],dp[1][1]=0;是0,则dp[1][1]=w[i],dp[1][0]=0
    34                     dp[pos][0] = w[i]*((bin[i]-'0')^0);
    35                     dp[pos][1] = w[i]*((bin[i]-'0')^1);
    36                     pos++;  i--; //i指向当前考虑的格雷码位,pos指向i的前一位对应的从右向左的第几个'?'
    37                     while(i && bin[i-1] == '?')
    38                     {
    39                         dp[pos][0] = max(dp[pos-1][1] + w[i], dp[pos-1][0]);
    40                         dp[pos][1] = max(dp[pos-1][0] + w[i], dp[pos-1][1]);
    41                         pos++; i--;
    42                     }
    43                     //前面的数字也要单独考虑,若bin[i-1]是1,则max_val=max(dp[pos-1][0] + w[i], dp[pos-1][1]);
    44                     dp[pos][bin[i-1] - '0'] = max(dp[pos-1][!(bin[i-1] - '0')] + w[i], dp[pos-1][bin[i-1] - '0']);
    45                     ans += dp[pos][bin[i-1] - '0'];
    46                     i--;
    47                 }
    48                 else // X11111 连数字,直接与前一位异或计算即可
    49                 {
    50                     while(i && bin[i-1] != '?')
    51                     {
    52                         ans += ((bin[i]-'0')^(bin[i-1]-'0')) * w[i];
    53                         i--;
    54                     }
    55                 }
    56             }
    57             else // X???? 连问号且尾不接数字,可以保证其格雷码'?'处全为1
    58             {
    59                 while(i && bin[i] == '?')
    60                 {
    61                     ans += w[i];
    62                     i--;
    63                 }
    64             }
    65         }
    66         printf("Case #%d: %d
    ", kase, ans);
    67     }
    68     return 0;
    69 }
    hdu 5375

    最近易激动,大约是亲戚来的缘故吧。有点想家了。

    加油吧,在这个优胜劣汰的游戏中,努力生存下去吧。

  • 相关阅读:
    docker 创建新的镜像到私有仓库
    docker 数据管理<1>
    docker 数据管理<1>
    docker 运行挂载磁盘
    docker 运行挂载磁盘
    docker 容器管理上
    docker 指定容器名字
    消息队列应用场景解析
    Apache软件基金会Member陈亮:一名开源拓荒者的 Apache之旅
    【干货贴】消息队列如何利用标签实现消息过滤
  • 原文地址:https://www.cnblogs.com/LLGemini/p/4723273.html
Copyright © 2011-2022 走看看