题目链接

https://codeforces.com/problemset/problem/998/C

解题思路

别人的正确思路:

任何一段0 1序列都可以看做是一串 0 然后用 1 切割开。首先,因为我们是要把目标串变成全1串,所以开头的1(和结尾的1)我们可以不去管它,所以我们可以把所有的串看做是这种(开头的1和结尾的1无所谓就全都省略)然后我们可以怎么做呢?例如:000 1 000 1 0000 1 00 1 00这个串,因为上面操作的花费与段的长度无关,所以我们可以把相邻的1合成一个1,相邻的0合成一个0。所以原串就可以转化成 0 1 0 1 0 1 0 1 0。
假设0分成的段的数量是num。

第一种方法,将最左边的01翻转,得到1 00 1 0 1 0 1 0;再把左侧的00 1翻转,得到11 000 1 0 1 0;以此类推,得到111 0000 1 0,得到1111 00000。翻转的次数为num-1,再对连续的0进行变换这种方法的花费为 (num-1)* x+y。

第二种方法,我们直接对每一段0实施操作二,使得其变为全1串,这样的花费是num * y。

所以显然,当x<=y时,我们选择第一种方案,当x>y时,我们选择第二中方案,统计0的段数,直接输出结果即可。

我的正确思路:
其实我自己都不知道我的思路,因为原来见过一道题,和这个很像,那道题myq是用dp做的,所以我一直在想如何dp,结果稀里糊涂的dp出来了(如果你要问myq是谁,他是wf第一,但这不算什么,更重要的是,他是我儿子
dp[i][0/1]的含义为前i个单元全部变成1的最小花费,第二维为0表示第i个单元没有与第i-1个单元发生翻转操作,为1表示第i个单元与第i-1个单元发生了翻转操作。(单元的含义为连续相同的1序列或0序列)
我不行了,我想试着讲解一下,结果发现我并不能讲出来……就是蒙了个AC……

别人的AC代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,x,y,cnt;
string str;
int main()
{
    cin>>n>>x>>y;
    cin>>str;

    if(str[0]=='0') cnt++;
    for(int i=1;i<n;i++)
    if(str[i]=='0' && str[i-1]!='0') cnt++;

    if(cnt==0)//特判
    {
        cout<<0<<endl;
        return 0;
    }
    if(x<=y) cout<<(cnt-1)*x+y<<endl;
    else cout<<cnt*y<<endl;
    return 0;
}

我的AC代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=3e5+10;
int cnt,n,x,y,f;
ll dp[N][2];
string str;
int main()
{
    cin>>n>>x>>y;
    cin>>str;
    f=str[0]-'0';
    cnt=1;
    for(int i=1;i<n;i++)
    {
        while(str[i]==str[i-1] && i<n) i++;
        if(i==n) break;
        cnt++;
    }
//    cout<<cnt<<endl;
    if(cnt==1)
    {
        cout<<(f==1?0:y)<<endl;
        return 0;
    } 
    memset(dp,0x3f,sizeof dp);
    if(f) dp[1][0]=y,dp[1][1]=y;
    else dp[1][0]=y,dp[1][1]=x+y;
    f^=1;
    for(int i=2;i<=cnt;i++,f^=1)
    {
        if(f) dp[i][1]=min(dp[i-1][1],dp[i-1][0])+x,dp[i][0]=min(dp[i-1][0],dp[i-1][1]);
        else  dp[i][1]=min(dp[i-1][1],dp[i-1][0])+x,dp[i][0]=min(dp[i-1][1],dp[i-1][0]+y);
    }
//    for(int i=2;i<=cnt;i++)
//    cout<<min(dp[i][0],dp[i][1])<<endl;
    cout<<min(dp[cnt][0],dp[cnt][1])<<endl;
    return 0;
}