題目描述
解題思路
題目大意:
將二進制數轉換爲格雷碼(二進制位上有若干個 ‘?’ , 則該位可爲0 或 1)
若格雷碼某位上爲1,則得到相應位上的分數,求最大分數.
轉換規則: B (二進制) -> G (格雷碼)
1 | 2 | … | n |
---|---|---|---|
… | |||
… |
考慮, dp[i][j]表示二進制 第i位 爲 j 時前i位的最大分數.
B[i] 有三種情況:
1) B[i] == 0 時, dp[i][0] 可以從兩種狀態轉移過來, dp[i-1][0] 和 dp[i-1][1]+
2) B[i] == 1 時, 同上 dp[i][1] 可從 dp[i-1][1] 和 dp[i-1][0]+
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;
}