CoderForce 180D-Name (构造+回溯)

Posted 真正的强者,从不埋怨黎明前的黑暗!!!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CoderForce 180D-Name (构造+回溯)相关的知识,希望对你有一定的参考价值。

题目大意:给两个字符串s,t,用s中的字符重新组合构造出按字典序最小的但比t大的新字符串。

题目分析:先统计s中各个字母出现的次数,然后从t的左端向右端依次构造出新串的每一位上的字母。这个过程我是用回溯实现的,因为只需进行到字典序比t大就可以立即停止,所以实际上花不了多少时间。

 

代码如下:

# include<iostream>
# include<string>
# include<algorithm>
# include<cstdio>
# include<vector>
# include<cstring>
using namespace std;

int n,m;
int vis[5005];
string p,q;
int cnt[26];
int ans[5005];

int isBigger()
{
    for(int i=1;i<=ans[0]&&i-1<m;++i){
        if(ans[i]<q[i-1]-‘a‘) return -1;
        if(ans[i]>q[i-1]-‘a‘) return 1;
    }
    if(ans[0]==m) return 0;
    else if(ans[0]>m) return 1;
    else return -1;
}

bool dfs(int i)
{
    int k=isBigger();
    if(k>0) return true;
    if(i>=m){
        if(k>0) return true;
        else if(k==0) return n>m;
        else if(k<0) return false;
    }
    for(char c=q[i];c<=‘z‘;++c){
        if(cnt[c-‘a‘]==0) continue;
        --cnt[c-‘a‘];
        ans[++ans[0]]=c-‘a‘;
        if(dfs(i+1)) return true;
        --ans[0];
        ++cnt[c-‘a‘];
    }
    return false;
}

int main()
{
    //while(cin>>p>>q){
        cin>>p>>q;
        n=p.size();
        m=q.size();

        memset(cnt,0,sizeof(cnt));
        for(int i=0;i<n;++i)
            ++cnt[p[i]-‘a‘];

        ans[0]=0;
        if(!dfs(0))
            printf("-1\n");
        else{
            for(int i=1;i<=ans[0];++i)
                cout<<(char)(ans[i]+‘a‘);
            for(int i=0;i<26;++i)
                for(int j=0;j<cnt[i];++j)
                    cout<<(char)(i+‘a‘);
            cout<<endl;
        }
    //}
    return 0;
}

  

以上是关于CoderForce 180D-Name (构造+回溯)的主要内容,如果未能解决你的问题,请参考以下文章

CoderForce 148D-Bag of mice (概率DP求概率)

HDU-6336-构造

如何构造循环API调用以使JSON结果可用?

linux四剑客常用命令汇总

css旋转180度怎么转

饼图----插件