這是今天的多校題,題意是,給你一個二進制字符串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;
}