因为傻逼错误导致绝杀失败,还没开放补题,先把代码放着,等开放了再试试能不能切(能切)
update:能补题了,不过wa了,对不起广大网友,我继续修改。
继续update:才发现思路没问题,不过我贴的代码细节写错了,总算过了这题,Yes!
我的思路是(不一定对,现在对了!!!,之前写了个背包复杂度400*t*n超时了,换成二进制没来得及debug):假设在第 i 位最多能打完d[ i ]场比赛,那么从第 i +1 位开始计分,设A得分的集合为S,假设从 i+1 到 j-1 A可以得1分或者3分,表示二进制就是1010,假设s[ j ] = 'A',那么A的得分就变成10100,s[ j ] = 'B',A的得分集合不变,s[ j ] = '?',那么A的得分就是1010 | 10100 = 11110,我们往后面枚举20次得分,如果在第 j 位,S&(1<<11)或者S&(1<<(j-i-11))不为0,表示当前可以结束一场比赛,那么更新d[ j ]=max(d[ j ], d[ i ]+1 ),算完20次得分后,如果能打成平局即S&(1<<10)不为0,那么我们继续往后每两次得分的去枚举,这个就很简单留给你来解决了。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=10005,inf=1e8;
int d[maxn];
char s[maxn];
void up(int& x,int y)
{
if(x<y)x=y;
}
int ok(char a,char b)
{
if(a=='?'||b=='?')return 2;
if(a==b)return 1;
return 0;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int ans=0;
scanf("%s",s+1);
int n=strlen(s+1);
for(int i=1;i<=n;i++)d[i]=-inf;
for(int i=0;i<=n-11;i++)
if(d[i]>=0)
{
int s1=1;
for(int j=i+1;j<=n&&j-i<=20;j++)
{
int s2=(s1<<1);
if(s[j]=='A')
s1=s2;
else if(s[j]=='?')
s1|=s2;
if(s1&(1<<11))
{
up(d[j],d[i]+1);
//printf("i=%d j=%d d[j]=%d\n",i,j,d[j]);
s1^=(1<<11);
}
if(j-i>=11)
{
int t=(1<<(j-i-11));
if(s1&t)
{
up(d[j],d[i]+1);
s1^=t;
}
}
}
int flag=1,mark=0;
if(!(s1&(1<<10)))flag=0;
if(flag)
for(int j=i+22;j-i<=50;j+=2)
{
int tmp=ok(s[j],s[j-1]);
if(tmp)
{
mark=1;
up(d[j],d[i]+1);
if(tmp==1)
break;
}
}
if(flag&&!mark)
up(d[i+22],d[i]);
}
for(int i=11;i<=n;i++)
up(ans,d[i]);
printf("%d\n",ans);
}
}
/*
212
????????????????????ABABABABABABABABABABABABABABABABABABABABA
*/
设d[ i ][ j ]为前 i 个挑战中完成了 j 个挑战所能得到的最大体力值,对于第 i+1 个挑战,我可以选择不挑战,那么d[ i+1][ j ]=max(d[i+1][ j ], d[ i ][ j]),选择挑战,那么d[ i+1 ][ j+1 ]=max(d[ i+1 ][ j+1 ],min(d[ i ][ j ], bi) - ai + ci ) (必须要min(d[ i ][ j ], bi) - ai > 0 才行)。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1005;
ll inf=1e18;
ll d[2][maxn];
void up(ll& x,ll y)
{
x=max(x,y);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,m,a,b,c,cur=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
d[cur][i]=0;
d[cur][0]=m;
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&a,&b,&c);
cur=!cur;
for(int j=0;j<=n;j++)d[cur][j]=0;
for(int j=0;j<=n;j++)
if(d[!cur][j]!=0)
{
int t=min(1ll*b,d[!cur][j]);
if(t>a)
up(d[cur][j+1],t-a+c);
up(d[cur][j],d[!cur][j]+c);
}
}
int ans=0;
for(int i=1;i<=n;i++)
if(d[cur][i])
ans=i;
printf("%d\n",ans);
}
}