• 1500. 生日礼物


    题目链接:

    题意:给出(n<=9)长度的两个数字a,b。可以做的操作是在a某一位上加1,或者交换相邻两位的位置。

    思路:

    直接BFS

    如果只有一个节点找去b的话,每个位置的操作为9个加操作和8个交换操作一共17个操作,那么对于9个位置就有17^9次方种

     这很明显1s跑不完的!!!

    那么我们就要用meet in the middle 的思想 去写

    把a,b换成字符串存进队列中。开一个map标记每个字符串的步数与来源(对于a转化来就标记0,对于b转换来就标记1)

    那么对于状态0的来说就是加操作,枚举长度然后对每个位做+1操作,要取模10!

    那么对于状态1的来说就是减操作,也就是枚举长度然后对每个位做+9操作,也要取模10!   (PS:这个9=-1+10)

    那么交换操作无论状态0还是1都是一样的。

    那么对于每次我们找到一个状态的s,判断其在hash表(就是那个map)中的来源是否与当前状态来源是否一样,一样则忽略,不一样就可以直接返回去到当前状态的步数+hash表中的状态步数+1

    然后特判一开始两个数字相等的情况(如果没有这个就是90分的代码emmm)

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define re register
    #define pb push_back
    #define fi first
    #define se second
    const int N=2e6+10;
    void read(int &a)
    {
        a=0;int d=1;char ch;
        while(ch=getchar(),ch>'9'||ch<'0')
            if(ch=='-')
                d=-1;
        a=ch^48;
        while(ch=getchar(),ch>='0'&&ch<='9')
            a=(a<<3)+(a<<1)+(ch^48);
        a*=d;
    }
    int n;
    string a,b;
    struct note
    {
        string s;
        int st,f;
    };
    map <string,pair<int,int> > vis;
    queue <note> q;
    int bfs()
    {
        q.push({a,0,0});q.push({b,0,1});
        while(!q.empty())
        {
            note t=q.front();
            q.pop();
            if(vis.count(t.s)) continue;
            vis[t.s].fi=t.st;vis[t.s].se=t.f;
            if(!t.f)
            {
                for(re int i=0;i<n;i++)
                {
                    string s=t.s;
                    s[i]=((s[i]-'0'+1)%10)+'0';
                    if(vis.count(s))
                    {
                        if(vis[s].se!=t.f) return vis[s].fi+t.st;
                        else continue;
                    }
                    else q.push({s,t.st+1,t.f});
                }
                for(re int i=1;i<n;i++)
                {
                    string s=t.s;
                    swap(s[i],s[i-1]);
                    if(vis.count(s))
                    {
                        if(vis[s].se!=t.f) return vis[s].fi+t.st;
                        else continue;
                    }
                    else q.push({s,t.st+1,t.f});
                }
            }
            else
            {
                for(re int i=0;i<n;i++)
                {
                    string s=t.s;
                    s[i]=((s[i]-'0'+9)%10)+'0';
                    if(vis.count(s))
                    {
                        if(vis[s].se!=t.f) return vis[s].fi+t.st;
                        else continue;
                    }
                    else q.push({s,t.st+1,t.f});
                }
                for(re int i=1;i<n;i++)
                {
                    string s=t.s;
                    swap(s[i],s[i-1]);
                    if(vis.count(s))
                    {
                        if(vis[s].se!=t.f) return vis[s].fi+t.st;
                        else continue;
                    }
                    else q.push({s,t.st+1,t.f});
                }
            }
        }
    }
    int main()
    {
        for(re int T=1;T<=3;T++)
        {
            vis.clear();
            while(!q.empty()) q.pop();
            read(n);
            cin>>a>>b;
            if(a==b)
            {
                puts("0");
                continue;
            }
            printf("%d
    ",bfs()+1);
        }
        return 0;
    }
  • 相关阅读:
    归并两路有序链表
    [转]两种高性能I/O设计模式(Reactor/Proactor)的比较
    linux 静态库使用经验
    系统性能调优经验
    编译-O 选项对性能提升作用
    [转]Linux shell中的那些小把戏
    shell函数传递带空格的参数
    标题清洗引发的算法(两个字符串的最长公共子串)
    正则表达式之Matcher类中group方法
    ConcurrentHashMap JDK 1.6 源码分析
  • 原文地址:https://www.cnblogs.com/acm1ruoji/p/11867001.html
Copyright © 2020-2023  润新知