题目链接:
题目大意:给你一个二进制串,带’?’的位置能够由你来决定填’1’还是’0’,补充完整之后转换成格雷码表示,每个位置都有一个权值a[i],仅仅有格雷码为’1’的位能够加上权值,问你终于权值之和最大为多少。
格雷码表示能够百度一下,在这里能够通俗一点讲:对于这么一个串,假设i位置是1,那么他后面的数就会变化(0变1、1变0),注意仅仅是看初始串。
比如:初始串为110,那么改变以后则为101,而不是100。
思路:考虑用dp解决,dp[i][j]表示对于第i个位置取j时的最大分数(j取0或者1)。
那么就有dp[i][0]=max(dp[i-1][0],dp[i-1][1]+a[i]);
dp[i][1]=max(dp[i-1][0]+a[i],dp[i-1][1]);
当j为?时,表明j可能为0或者1。那么久两者都考虑处理一遍。
注意初始化。
#include#include #include #define max(a,b) a>b?
a:b int dp[200005][2],a[200005]; int main() { int T,i,j,l,k,t=0; char s[200005],c[200005]; scanf("%d",&T); while(T--) { t++; scanf("%s",s); l=strlen(s); for(i=0;i<l;i++) c[i+1]=s[i]; for(i=1;i<=l;i++) scanf("%d",&a[i]); for(i=0;i<200005;i++) { dp[i][0]=-999999; dp[i][1]=-999999; } if(c[1]=='0')dp[1][0]=0; if(c[1]=='1')dp[1][1]=a[1]; if(c[1]=='?'){ dp[1][0]=0; dp[1][1]=a[1]; } for(i=2;i<=l;i++) { if(c[i]=='0'){ dp[i][0]=max(dp[i-1][0],dp[i-1][1]+a[i]); } if(c[i]=='1'){ dp[i][1]=max(dp[i-1][0]+a[i],dp[i-1][1]); } if(c[i]=='?
'){ dp[i][0]=max(dp[i-1][0],dp[i-1][1]+a[i]); dp[i][1]=max(dp[i-1][0]+a[i],dp[i-1][1]); } } printf("Case #%d: ",t); if(c[l]=='0')printf("%d\n",dp[l][0]); else if(c[l]=='1')printf("%d\n",dp[l][1]); else printf("%d\n",max(dp[l][0],dp[l][1])); } return 0; }