【简单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

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

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

原文地址:https://www.cnblogs.com/LLGemini/p/4723273.html