思路:思维题,对于两端连续1中间的0进行计数,0的个数num0与b的乘积即此时将中间连续0填满所需的消费,如果此时的消费小于直接爆破所需的消费a则采取填0爆破的方式,即答案ans+=num0*b,否则直接进行爆破,ans+=a,注意下字符串开头的连续0段是无效的,开始时直接过滤掉,对于第一个连续1段,要先加上,因为上述操作是在已经出现连续1段的情况下进行的,漏了最开始的连续1段,因此要加上去,如果没有第一个连续1段则不加
ac代码 46ms:
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdio>
#define INF 0x3f3f3f3f
using namespace std;
const int N=1e5+10;
int dp[N];
char s[N];
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int t;
cin>>t;
while(t--){
int a,b;
cin>>a>>b;
cin>>(s+1);
int len=strlen(s+1);
int ans=0,num0=0,i=1;
while(s[i]=='0'&&i<=len)i++;
if(i<=len)ans+=a;
for(;i<=len;i++){
if(s[i]=='0')num0++;
else if(s[i]=='1'&&(s[i+1]=='0'||i==len)){
if(num0*b<=a)ans+=num0*b;
else ans+=a;
num0=0;
}
}
cout<<ans<<endl;
}
return 0;
}