返回顶部

2018 ICPC Asia Jakarta Regional Contest

https://codeforc.es/gym/102001

L Binary String

签到题,给一个ll范围内的整数K,以及一个二进制串S,求从S中移除尽可能少的字符使得S表示的数不超过K。

思路:贪心+dfs,首先优先移除最高位的1,假如移除这个1之后不会导致前导零出现,这样是最优的。否则,有两种选择,要么从后面移除最高的1或者没有1则随意移除一个0,要么把整个1000...0串移除,把新的1暴露出来,复杂度可能偏高。预处理一个上界,就是不进行移除前导零所得到的答案。有机会根据这个上界进行一定的最优性剪枝。但复杂度仍然玄学。事实上这个预处理出来的就是最优答案,因为删除1肯定比删除0要好,而优先删除高位1肯定更好。上面的两种路线事实上是重复了。一开始的思路就是对的,只是没开longlong溢出了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
 
int ans;
 
void dfs(ll n,string s,int cnt)
{
    if(cnt>=ans)
        return;
    ll cur=0;
    for(int i=0; i<s.length(); ++i)
    {
        cur=(cur*2ll)+(s[i]-'0');
    }
    if(cur<=n)
    {
        ans=cnt;
        return;
    }
    if(s.length()>1&&s[1]=='1')
    {
        dfs(n,s.substr(1,s.length()),cnt+1);
    }
    else
    {
 
        for(int i=1; i<s.length(); ++i)
        {
            if(s[i]=='1')
            {
                string t=s.substr(0,i)+s.substr(i+1,s.length());
                dfs(n,t,cnt+1);
                t=s.substr(i,s.length());
                dfs(n,t,cnt+s.length()-t.length());
                return;
            }
        }
 
        dfs(n,s.substr(0,s.length()-1),cnt+1);
        return;
    }
}
 
int main()
{
#ifdef local
    freopen("lyz.in","r",stdin);
#endif // local
    ll n;
    while(cin>>n)
    {
        string s;
        cin>>s;
 
        string cs=s;
 
        ll cur=0;
        for(int i=0; i<s.length(); ++i)
        {
            cur=(cur*2ll)+(s[i]-'0');
        }
 
        int cnt=0;
        while(cur>n)
        {
            if(s.length()>1&&s[1]=='1')
            {
                ++cnt;
                s=s.substr(1,s.length());
            }
            else
            {
                bool suc=0;
                for(int i=1; i<s.length(); ++i)
                {
                    if(s[i]=='1')
                    {
                        ++cnt;
                        string t=s.substr(0,i)+s.substr(i+1,s.length());
                        s=t;
                        suc=1;
                        break;
                    }
                }
                if(!suc)
                {
                    ++cnt;
                    s=s.substr(0,s.length()-1);
                }
            }
 
            cur=0;
            for(int i=0; i<s.length(); ++i)
            {
                cur=(cur*2ll)+(s[i]-'0');
            }
            //cout<<s<<endl;
        }
 
        ans=cnt;
 
        dfs(n,cs,0);
 
        printf("%d\n",ans);
    }
}

A. Edit Distance

给一个二进制串S,求一个等长的二进制串T,使得S变为T至少要超过len(S)/2步。每步可以是增删改一个位置。

首先0和1数量不等可以随便构造。等长的情况为什么要这样构造当时没有想清楚,但是感觉这样是对的。首先把开头元素反向,后面接一串反向串。比如原串是1开头的,就搞0111...1,原串是0开头的就搞1000...0,为什么会这样呢?

首先原串串长必为偶数,设为2l,原串是1???...?,我构造0111...1,那么这个1必定要改成0或者删掉,花费至少为1。因为原串的1和0数量相等,所以原串后面有l个0,他们都要变成1,所以至少花费l+1步。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
 
char s[300000];
int main()
{
#ifdef local
    freopen("lyz.in","r",stdin);
#endif // Yinku
    int T,n=0;
    while(~scanf("%s",s+1))
    {
        n=strlen(s+1);
        int o=0,y=0;
        for (int i=1; i<=n; i++)
        {
            if (s[i]=='1')
                y++;
            else
                o++;
        }
        if (y==1 && o==1)
            if (s[1]=='1')
            {
                printf("01\n");
                continue;
            }
            else
            {
                printf("10\n");
                continue;
            };
        if (y>o)
        {
            for (int i=1; i<=n; i++)
                printf("0");
            printf("\n");
        }
        else if (y<o)
        {
            for (int i=1; i<=n; i++)
                printf("1");
            printf("\n");
        }
        else if (y==o)
        {
            if (s[1]=='1')
            {
                printf("0");
                for (int i=1; i<=n-1; i++)
                    printf("1");
                printf("\n");
            }
            else
            {
                printf("1");
                for (int i=1; i<=n-1; i++)
                    printf("0");
                printf("\n");
            }
        }
    }
}
posted @ 2019-09-04 23:03  Inko  阅读(472)  评论(0编辑  收藏  举报