题意:
给出一个二进制数字,由0、1和?组成,最长有200000位,我们要把该二进制数字转化成格雷码,?的位置我们可以随便填1或者0,我们设该二进制的位数是n,题中给出n个数字,代表如果格雷码的第i位是1,我们就可以吧a[i]拿走,问我们能拿走的最大值。
思路:
首先我们要知道二进制是如何转化成格雷码的:
然后我们可以进行dp了。
我们设状态为dp[i][j]=k 表示前i位都填完且第i位填j我们能得到的最大值,那么转移方程如下:
dp[i][1]=max(dp[i-1][1],dp[i-1][0]+a[i]);
dp[i][0]=max(dp[i-1][0],dp[i-1][1]+a[i]);
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<map>
#include<queue>
#include<vector>
#include<string>
#include<cstdlib>
#include<cmath>
using namespace std;
const int maxn=200005;
const int inf=-1000000000;
string two;
int a[maxn+5];
int dp[maxn+5][3];
int main()
{
int t;
int cas=1;
scanf("%d",&t);
while(t--)
{
cin>>two;
int len=two.size();
for(int i=1;i<=len;i++)
scanf("%d",&a[i]);
dp[0][0]=0;
dp[0][1]=inf;
for(int i=1;i<=len;i++)
{
if(two[i-1]=='1')
{
dp[i][1]=max(dp[i-1][1],dp[i-1][0]+a[i]);
dp[i][0]=inf;
}
else if(two[i-1]=='0')
{
dp[i][0]=max(dp[i-1][0],dp[i-1][1]+a[i]);
dp[i][1]=inf;
}
else
{
dp[i][1]=max(dp[i-1][1],dp[i-1][0]+a[i]);
dp[i][0]=max(dp[i-1][0],dp[i-1][1]+a[i]);
}
}
printf("Case #%d: ",cas++);
printf("%d\n",max(dp[len][1],dp[len][0]));
}
return 0;
}