原题链接: https://vjudge.net/problem/1558510/origin
思路:先预处理构造出两个按‘1’开头排列和按‘0’开头排列的序列,然后计算其中的‘1’的个数,如果与原序列输入的‘1’个数相同,那么可以进行比较,取其中最小的转换次数输出。
比较关键的是compare函数:
如果两个序列a,b,在相同位置上,我们考虑两边‘1’的情况
1:如果同时为‘1’,则不需要转换,sum+=ans; ans=0;
2:如果a为‘1’,b为‘0’,那么,sum+=ans; ans++;
3.如果a为‘0’,b为‘1’,那么 sum+=ans; ans--;
ps:其实也可以写个swap函数,直接暴力模拟,也是可以AC的。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
char s1[20],s2[20],s[20];
char c[20],c1[20];
int n,m;
int a[20];
int t1,t2;
int tt1,tt2,tt3;
//预处理以‘1’开头的序列与以‘0’开头的序列
void build(int k,int d)
{
for(int i=0;i<k;i++)
{
if(d%2==0)
{
s1[t1++]='1';
tt2++;
}
else s1[t1++]='0';
}
for(int i=0;i<k;i++)
{
if(d%2==0)
{
s2[t2++]='0';
}
else{
s2[t2++]='1';
tt3++;
}
}
}
//关键比较函数
int compare(char c[],char c1[])
{
int sum=0;
int ans=0;
for(int i=0;i<n;i++)
{
sum+=abs(ans);
if(c[i]=='1')
{
ans++;
}
if(c1[i]=='1')
{
ans--;
}
}
return sum;
}
int solve()
{
int ans =1<<29;
if(tt1==tt2)
{
ans=compare(s,s1);
}
if(tt1==tt3)
{
ans=min(compare(s,s2),ans);
}
return ans;
}
int main()
{
while(cin>>n>>m)
{
tt1=tt2=tt3=0;
t1=t2=0;
for(int i=0;i<n;i++)
{
cin>>s[i];
if(s[i]=='1') tt1++;
}
for(int i=0;i<m;i++)
{
cin>>a[i];
build(a[i],i);
}
cout<<solve()<<endl;
}
return 0;
}