这是今天的多校题,题意是,给你一个二进制字符串s,里面有‘0’,‘1’,‘?’三种字符,?代表不确定,可以是0,也可以是1,取决于你。然后再给你大小为字符串长度的整数数组a。你要先将字符串s转换成对应的格雷码字符串s',a[i]对应s'[i],当s'[i]==‘1’时,你可以得到a[i],问,你最多得到的a[i]之和是多少?
今天,这道题让人很伤心,我们题意理解对了,但题目中给的图片是3个字符的格雷码,所以我们以为格雷码是三个三个转换的。提交的程序一直WA,没有过,最后一小时,我们才开始意识到可能是格雷码的转换问题,最后找到了定义,才恍然大悟。我们于是用搜索,但剪枝没成功,TLE了,然后,想到dp,但时间不够,还有最后几分钟,草草写了程序,就交了,又WA。赛后,经过调试,终于过了。哎,把“坑爹”的题目的格雷码转换图发上来吧
格雷码转换规则是这样的
最后把赛后调试过了的代码发上来吧
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
char s[200010];
int a[200010];
int dp[200010][2];
int main()
{
int cc;
cin>>cc;
int cnt=0;
while(cnt<cc)
{
cnt++;
memset(s,0,sizeof(s));
memset(a,0,sizeof(a));
memset(dp,0,sizeof(dp));
scanf(" %s",s);
int n=strlen(s);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
dp[0][0]=0;
dp[0][1]=0;
if(s[0]=='1')
{
dp[0][1]=a[0];
}
else if(s[0]=='?')
{
dp[0][1]=a[0];
dp[0][0]=0;
}
for(int i=1;i<n;i++)
{
if(s[i]=='1')
{
if(s[i-1]=='0')
dp[i][1]=dp[i-1][0]+a[i];
else if(s[i-1]=='1')
dp[i][1]=dp[i-1][1];
else
{
dp[i][1]=max(dp[i-1][0]+a[i],dp[i-1][1]);
}
}
else if(s[i]=='0')
{
if(s[i-1]=='0')
dp[i][0]=dp[i-1][0];
else if(s[i-1]=='1')
dp[i][0]=dp[i-1][1]+a[i];
else
{
dp[i][0]=max(dp[i-1][1]+a[i],dp[i-1][0]);
}
}
else
{
if(s[i-1]=='0')
{
dp[i][1]=dp[i-1][0]+a[i];
dp[i][0]=dp[i-1][0];
}
else if(s[i-1]=='1')
{
dp[i][0]=dp[i-1][1]+a[i];
dp[i][1]=dp[i-1][1];
}
else
{
dp[i][0]=max(dp[i-1][1]+a[i],dp[i-1][0]);
dp[i][1]=max(dp[i-1][0]+a[i],dp[i-1][1]);
}
}
}
int sum=0;
sum=max(dp[n-1][1],dp[n-1][0]);
cout<<"Case #"<<cnt<<": "<<sum<<endl;
}
return 0;
}