现在我还想不明白这道题为什么要这么做,先存着,以后慢慢想,为什么每次做相邻的移动时,要这么
算???据说是每次移动的步数相等的,表达式ans+=min(y,x*len-i);其中len是要交换的1和0之间交换的次数,
而且是从前面遍历,对于每一个0都会找到最后一个1与它交换。然后求最后ans的值就行了
别人的代码:以后我会删了写上自己的
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int const MAX = 1e5;
char s[MAX];
int idx[MAX];
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int x, y;
scanf("%d %d",&x, &y);
scanf("%s", s);
int len = strlen(s), cnt = 0;
for(int i = len - 1; i >= 0; i--)
if(s[i] == '1')
idx[cnt ++] = i;
int ans = 0, now = 0;
for(int i = 0; i < cnt; i++)
if(s[i] == '0')
ans += min(y, x * (idx[now ++] - i));
printf("%d\n", ans);
}
}
昨天,跟g讨论了一下,知道了这道题这么做的原因,1和1是不能交换的,比如说01101这串数字,如果想把最后的1和最前面的0交换的话,可以通过直接换和相邻换,相邻换的次数是5-1=4次,过程:第一次:10101;第二次:11001;第三次:11010;第四次:11100;也就说并不是把最后一个1放到最前面,只要最终结果是一样的就好,前面有1就把他们先移过去。总结可得:如果当前1的位置为pos1,0的位置为pos0,那么我们可以通过花费y直接对他们进行交换,或者花费(pos1-pos0)*x对他们进行若干次的相邻交换,这样我们就可以得出公式:min(y,(pos1-pos0)*x);这道题好奇怪,我不明白为什么我从前往后找1的时候会超时,从后往前找就A了,明天就要去参加省赛了,怎么没有一点点激动啊,贴代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#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);
}
}