Problem Description
给一个长度为n(n <= 10^5)的“01”串,你可以任意交换一个为0的位和一个为1的位,若这两位相邻,花费为X,否则花费为Y。求通过若干次交换后将串中的“1”全部变换到“0”前面的最小花费。
Input
第一行一个整数T(1 <= T <= 10),表示测试数据的组数。接下来3*T行,每组数据三行,第一行为整数X(1 <= X <= 10^3),第二行为整数Y(X <= Y <= 10^3),第三行是“01”串。
Output
最小花费。
Sample Input
2
1
2
1100
1
2
0011
Sample Output
0
3
这个题一开始暴力稳超时。
先附上一开始的代码,再附上后来去了一个for后的代码。。。
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
char s[100005];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int x,y;
scanf("%d%d",&x,&y);
scanf("%s",&s);
int flag1=0,flag2=0;
int sum=0;
for(int i=0;i<strlen(s);i++)
{
if(s[i]=='0'&&flag1==0)
{
flag1=i;
for(int k=strlen(s)-1;k>i;k--)
{
if(s[k]=='1')
{
flag2=k;
break;
}
}
if(flag2-flag1!=1&&flag2>flag1)
{
sum+=y;
s[flag1]='1';
s[flag2]='0';
}
else if(flag2-flag1==1&&flag2>flag1)
{
sum+=x*(flag2-flag1);
s[flag1]='1';
s[flag2]='0';
}
}
}
printf("%d\n",sum);
}
return 0;
}
后来精简后的代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
char a[100001];
int b[50001];
int main()
{
int t,s,i,x,y;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&x,&y);
scanf("%s",a);
s=0;
for(i=strlen(a)-1; i>=0; i--)
{
if(a[i]=='1')
b[s++]=i;;
}
int sum=0,cnt=0;
for(i=0; i<s; i++)
{
if(a[i]=='0')
{
sum+=min(y,(b[cnt++]-i)*x);
}
}
printf("%d\n",sum);
}
return 0;
}