【01串问题】
【01串问题】
结论题
小红的好01串修改
https://ac.nowcoder.com/acm/contest/114111/C
题目大意
思路
首先要发现一些显然的结论
(1)01串要相邻两不同->很显然只有两种方式:01010101/10101010
(2)每次修改相邻的两个->当一个点不满足要求的时候必须要改,下一个点跟着改就行
因为每个点都会被枚举到,所以直接一个方向扫一遍即可
->无解的情况?最后一个点不能被改
代码
const int N=3e5+10;
int n;
string s;
string ss;
void solve(){
cin>>n;
cin>>s;
ss=s;
string tmp1,tmp2;
int idx=0;
for(int i=0;i<n;i++){
tmp1+=(char)(idx+'0');
idx^=1;
}
idx=1;
for(int i=0;i<n;i++){
tmp2+=(char)(idx+'0');
idx^=1;
}
int flag1=1,ans1=0;
for(int i=0;i<n;i++){
if(i==n-1){
if(tmp1[i]!=s[i]){
flag1=0;
continue;
}
}
if(tmp1[i]!=s[i]){
ans1++;
s[i]=tmp1[i];
if(s[i+1]=='1') s[i+1]='0';
else s[i+1]='1';
}
}
s=ss;
//cout<<tmp1<<" "<<tmp2<<endl;
int flag2=1,ans2=0;
for(int i=0;i<n;i++){
if(i==n-1){
if(tmp2[i]!=s[i]){
flag2=0;
continue;
}
}
if(tmp2[i]!=s[i]){
ans2++;
s[i]=tmp2[i];
if(s[i+1]=='1') s[i+1]='0';
else s[i+1]='1';
}
}
int ans=inf_int;
if(flag1) ans=min(ans,ans1);
if(flag2) ans=min(ans,ans2);
if(ans==inf_int) cout<<"-1"<<endl;
else cout<<ans<<endl;
}
DP
Flip to Gather
https://atcoder.jp/contests/abc408/tasks/abc408_d
题目大意
1->0 0->1可以随意转换 ->这里看出可以设状态dp
最后只能留1串连续的1
代码
int n;
string s;
/*
每个都可以反转->有状态->【线性dp】
dp[i][j]
第二维状态:0 还没开始选->0 只能由“没开始选”状态转移来
1 开始选了但是没选完->1 可以是第一个开始选的 也可以是之前选过的
2 已经选完了->2 可以是第一个地方不选的 也可以是之前就不选的
+1 代表修改
*/
void solve(){
cin>>n;
cin>>s;
s=' '+s;
vector<array<int,3>> dp(n+1,{INF_INT,INF_INT,INF_INT});
dp[0]={0,0,0};
for(int i=1;i<=n;i++){
if(s[i]=='1'){
dp[i][0]=dp[i-1][0]+1;
dp[i][1]=min(dp[i-1][1],dp[i-1][0]);
dp[i][2]=min(dp[i-1][1]+1,dp[i-1][2]+1);
}
else{
dp[i][0]=dp[i-1][0];
dp[i][1]=min(dp[i-1][1]+1,dp[i-1][0]+1);
dp[i][2]=min(dp[i-1][1],dp[i-1][2]);
}
}
int ans=min(dp[n][0],min(dp[n][1],dp[n][2]));
cout<<ans<<endl;
}