1806. Mobile Telegraphs

http://acm.timus.ru/problem.aspx?space=1&num=1806

只要算法对 ural 一般不会卡时间的

这个题是一个简单的最短路 spfa

关键在于找边 找边的方法是 对于每一个点 枚举它的所有可能的变化 搜索是否有和变化后的字符串一样的

搜索的时候既可以用 map  也可以 自己写字典树

map 写起来简单 不过 字典树效率要高

注意边的个数 要在 N*50

代码1:

#include<iostream>

#include<stdio.h>

#include<string.h>

#include<math.h>

#include<algorithm>

#include<vector>

#include<set>

#include<map>

#include<string>

#include<queue>

#include<stack>

#include <iomanip>

using namespace std;

#define LL long long

const int INF=0x3f3f3f3f;

const int N=50005;

int head[N],I;

struct node

{

    int j,next,t;

}side[N*50];

int cost[N];

int f[N];

bool in[N];

int dist[N];

char s[N][12];

stack<int>st;

struct node1

{

    int k;

    struct node1 *next[10];

};

struct node1 *root;

void add(int i,int j,int t)

{//cout<<i<<" "<<j<<" "<<t<<endl;

    side[I].j=j;

    side[I].t=t;

    side[I].next=head[i];

    head[i]=I++;

}

int costtime(int i,int j)

{

    for(int x=0;x<10;++x)

    {

        if(s[i][x]!=s[j][x])

        return cost[x];

    }

    return 0;

}

bool spfa(int st,int nd)

{

    memset(in,false,sizeof(in));

    memset(dist,-1,sizeof(dist));

    queue<int>qt;

    qt.push(st);

    in[st]=true;

    dist[st]=0;

    while(!qt.empty())

    {

        int x=qt.front();qt.pop();

        in[x]=false;

        for(int t=head[x];t!=-1;t=side[t].next)

        {

            int j=side[t].j;

            if(dist[j]==-1||dist[j]>dist[x]+side[t].t)

            {



                dist[j]=dist[x]+side[t].t;

                f[j]=x;

                if(!in[j])

                {

                    in[j]=true;

                    qt.push(j);

                }

            }

        }

    }



    if(dist[nd]==-1)

    return false;

    return true;

}

void insert(int x)

{//cout<<x<<endl;

    struct node1 *w,*t=root;

    for(int i=0;i<10;++i)

    {

        if(t->next[s[x][i]-'0']==NULL)

        {

            w=new node1;

            for(int j=0;j<10;++j)

            w->next[j]=NULL;

            t->next[s[x][i]-'0']=w;

        }

        t=t->next[s[x][i]-'0'];

    }

    t->k=x;

}

int Fnum(int x)

{

    struct node1 *t=root;

    for(int i=0;i<10;++i)

    {

        if(t->next[s[x][i]-'0']==NULL)

        return 0;

        t=t->next[s[x][i]-'0'];

    }

    return t->k;

}

int main()

{

    //freopen("data.in","r",stdin);

    int n;

    while(scanf("%d",&n)!=EOF)

    {

        root=new node1;

        for(int i=0;i<10;++i)

        root->next[i]=NULL;

        for(int i=0;i<10;++i)

        scanf("%d",&cost[i]);

        getchar();

        for(int i=1;i<=n;++i)

        {

            gets(s[i]);

            insert(i);

        }

        memset(head,-1,sizeof(head));

        I=0;

        int k;

        for(int i=1;i<=n;++i)

        {

            for(int l=0;l<10;++l)

            {

                char ctmp=s[i][l];

                for(char c='0';c<='9';++c)

                {

                    if(ctmp==c)

                    continue;

                    s[i][l]=c;

                    if((k=Fnum(i)))

                    {

                        s[i][l]=ctmp;

                        add(i,k,costtime(i,k));

                        continue;

                    }

                }

                s[i][l]=ctmp;

            }

            for(int l=0;l<10;++l)

            for(int r=l+1;r<10;++r)

            {

                if(s[i][l]==s[i][r])

                continue;

                swap(s[i][l],s[i][r]);

                if((k=Fnum(i)))

                {

                    swap(s[i][l],s[i][r]);

                    add(i,k,costtime(i,k));

                    continue;

                }

                swap(s[i][l],s[i][r]);

            }

        }

        if(!spfa(1,n))

        printf("-1\n");

        else

        {

            while(!st.empty())

            st.pop();

            int k=n;

            while(k!=1)

            {

                st.push(k);

                k=f[k];

            }

            printf("%d\n",dist[n]);

            printf("%d\n",st.size()+1);

            printf("1");

            while(!st.empty())

            {

                printf(" %d",st.top());

                st.pop();

            }

            printf("\n");

        }

    }

    return 0;

}

 代码2:

#include<iostream>

#include<stdio.h>

#include<string.h>

#include<math.h>

#include<algorithm>

#include<vector>

#include<set>

#include<map>

#include<string>

#include<queue>

#include<stack>

#include <iomanip>

using namespace std;

#define LL long long

const int INF=0x3f3f3f3f;

const int N=50005;

int head[N],I;

struct node

{

    int j,next,t;

}side[N*50];

int cost[N];

map<string,int>mt;

map<string,int>::iterator it;

int f[N];

bool in[N];

int dist[N];

string s[N];

stack<int>st;



void add(int i,int j,int t)

{//cout<<i<<" "<<j<<" "<<t<<endl;

    side[I].j=j;

    side[I].t=t;

    side[I].next=head[i];

    head[i]=I++;

}

int costtime(int i,int j)

{

    for(int x=0;x<10;++x)

    {

        if(s[i][x]!=s[j][x])

        return cost[x];

    }

    return 10;

}

bool spfa(int st,int nd)

{

    memset(in,false,sizeof(in));

    memset(dist,-1,sizeof(dist));

    queue<int>qt;

    qt.push(st);

    in[st]=true;

    dist[st]=0;

    while(!qt.empty())

    {

        int x=qt.front();qt.pop();

        in[x]=false;

        for(int t=head[x];t!=-1;t=side[t].next)

        {

            int j=side[t].j;

            if(dist[j]==-1||dist[j]>dist[x]+side[t].t)

            {



                dist[j]=dist[x]+side[t].t;

                f[j]=x;

                if(!in[j])

                {

                    in[j]=true;

                    qt.push(j);

                }

            }

        }

    }



    if(dist[nd]==-1)

    return false;

    return true;

}

int main()

{

    //freopen("data.in","r",stdin);

    int n;

    while(cin>>n)

    {

        for(int i=0;i<10;++i)

        cin>>cost[i];

        mt.clear();

        for(int i=1;i<=n;++i)

        {

            cin>>s[i];

            mt[s[i]]=i;

        }

        memset(head,-1,sizeof(head));

        I=0;

        for(int i=1;i<=n;++i)

        {

            s[0]=s[i];

            for(int l=0;l<10;++l)

            {

                char ctmp=s[i][l];

                for(char c='0';c<='9';++c)

                {

                    if(ctmp==c)

                    continue;

                    s[i][l]=c;

                    if((it=mt.find(s[i]))!=mt.end())

                    add(i,it->second,costtime(0,it->second));

                }

                s[i][l]=ctmp;

            }

            for(int l=0;l<10;++l)

            for(int r=l+1;r<10;++r)

            {

                if(s[i][l]==s[i][r])

                continue;

                swap(s[i][l],s[i][r]);

                if((it=mt.find(s[i]))!=mt.end())

                add(i,it->second,costtime(0,it->second));

                swap(s[i][l],s[i][r]);

            }

        }

        if(!spfa(1,n))

        cout<<"-1"<<endl;

        else

        {

            while(!st.empty())

            st.pop();

            int k=n;

            while(k!=1)

            {

                st.push(k);

                k=f[k];

            }

            cout<<dist[n]<<endl;

            cout<<(st.size()+1)<<endl;

            cout<<"1";

            while(!st.empty())

            {

                cout<<" "<<st.top();

                st.pop();

            }

            cout<<endl;

        }

    }

    return 0;

}

 

 

你可能感兴趣的:(mobile)