HDU 5375 Gray code //遞推dp

題目描述

HDOJ 5375 Gray code

解題思路

題目大意:
將二進制數轉換爲格雷碼(二進制位上有若干個 ‘?’ , 則該位可爲0 或 1)
若格雷碼某位上爲1,則得到相應位上的分數,求最大分數.

轉換規則: B (二進制) -> G (格雷碼)

1 2 n
B1 B2 Bn
G1 = B1 G2 = B1 ^ B2 Gn = Bn1 ^ Bn

考慮, dp[i][j]表示二進制 第i位 爲 j 時前i位的最大分數.
B[i] 有三種情況:
1) B[i] == 0 時, dp[i][0] 可以從兩種狀態轉移過來, dp[i-1][0] 和 dp[i-1][1]+ai (前提是dp[i-1][1]是合法狀態), 然後二者取大;
2) B[i] == 1 時, 同上 dp[i][1] 可從 dp[i-1][1] 和 dp[i-1][0]+ai ;
3) B[i] == ? 時, 此時1)和2)都要進行

參考代碼

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
inline int max(int a, int b) {return a>b?a:b;}
const int MAX_N = 200010;
int a[MAX_N], dp[MAX_N][2];
char s[MAX_N];
int main() {
    int T, kase = 1;
    scanf("%d", &T);
    while (T--) {
        scanf("%s", s);
        int len = strlen(s);
        for(int i = 0; i < len; ++i) scanf("%d", a+i);
        memset(dp, -1, sizeof(dp));//初始化所有狀態都爲非法
        dp[0][0] = 0;//考慮到格雷碼第一位的特性(G1 = B1) 故只初始化dp[0][0] = 0
        for (int i = 0; i < len; ++i) {
            if (s[i] == '0' || s[i] == '?')   dp[i+1][0] = max(dp[i][0], dp[i][1] + (dp[i][1] == -1 ? 0 :a[i]));
            if (s[i] == '1' || s[i] == '?')   dp[i+1][1] = max(dp[i][1], dp[i][0] + (dp[i][0] == -1 ? 0 :a[i]));
        }
        printf("Case #%d: %d\n", kase++, max(dp[len][0], dp[len][1]));
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章