eoj官方题解:
写的时候并没有采用他后半段动态规划的方法。
直接遍历字符串,先把连续的1 变为1 0 … 0 -1这样的形式
再把 -1 和 1 合并
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
int a[2000010]={0};
int main(){
string x;
cin>>x;
int cnt=0;
for(int i=x.size()-1;i>=0;i--)
{
if(x[i]=='0'){a[++cnt]=0;}
else
{
if(i==0||x[i-1]=='0')
{
a[++cnt]=1;
}
else
{
a[++cnt]=-1;
int p=i-1;
while(p>=0&&x[p]=='1')
{
a[++cnt]=0;
p--;
}
if(p>=0)
{
x[p]=1;///注意这里改的是原字符串,因为这个位置新生成了1,若后面还有1,则连续,那么这个位置就应该记录为-1了,所以在里先把原字符串改成1,通过下一句代码,让这个位置能进入下一次判断(是否能和后面的字符形成连续1),再确定这个位置的答案(是1还是-1)
i=p+1;
}
else
{
a[++cnt]=1;///后面没有字符了,直接记录答案
i=p;
}
}
}
}
for(int i=1;i<cnt;i++)///合并-1 1
{
if(a[i]==1&&a[i+1]==-1)
{
a[i]=-1;
a[i+1]=0;
}
else if(a[i]==-1&&a[i+1]==1)
{
a[i]=1;
a[i+1]=0;
}
}
while(a[cnt]==0)cnt--;
cout<<cnt<<endl;
for(int i=cnt;i>1;i--)cout<<a[i]<<" ";
cout<<a[1]<<endl;
return 0;
}