zoukankan      html  css  js  c++  java
  • URAL 1806 Mobile Telegraphs

    URAL_1806

        这个题目思路比较明显,将边的关系找出来之后做最短路即可,但是由于N巨大,直接判断两个字符串能否转化是划不来的。

        于是不妨将所有字符串放到哈希表中,然后对于当前字符串,枚举这个字符串改变一位、交换两位的情况,然后看能否在哈希表中找到变化之后的字符串,这样对于每个字符串至多枚举200种情况,复杂度还是可以接受的。

    #include<stdio.h>
    #include<string.h>
    #define MAXD 50010
    #define HASH 1000003
    #define INF 0x3f3f3f3f
    int N, D, cost[15], head[HASH], next[MAXD];
    char b[MAXD][15], code[15];
    int dis[MAXD], pre[MAXD], tree[4 * MAXD];
    int hash(char *str)
    {
        int i, h = 0, seed = 131;
        while(*str)
            h = h * seed + *(str ++);
        return (h & 0x7fffffff) % HASH;    
    }
    void Insert(int s)
    {
        int h = hash(b[s]);
        next[s] = head[h];
        head[h] = s;    
    }
    int search(char *str)
    {
        int i, h = hash(str);
        for(i = head[h]; i != -1; i = next[i])
            if(strcmp(b[i], str) == 0)
                break;
        return i;
    }
    void init()
    {
        int i;
        for(i = 0; i < 10; i ++)
            scanf("%d", &cost[i]);
        memset(head, -1, sizeof(head));
        for(i = 1; i <= N; i ++)
        {
            scanf("%s", b[i]);
            Insert(i);    
        }
    }
    void update(int i)
    {
        for(; i ^ 1; i >>= 1)
            tree[i >> 1] = dis[tree[i]] < dis[tree[i ^ 1]] ? tree[i] : tree[i ^ 1];
    }
    void Swap(char &x, char &y)
    {
        char t;
        t = x, x = y, y = t;    
    }
    void dfs(int cur, int n)
    {
        if(cur == 1)
        {
            printf("%d\n%d", n, cur);
            return ;
        }
        dfs(pre[cur], n + 1);
        printf(" %d", cur);
    }
    void solve()
    {
        int i, j, x, y;
        for(D = 1; D < N + 2; D <<= 1);
        memset(tree, 0, sizeof(tree));
        memset(dis, 0x3f, sizeof(dis));
        dis[1] = 0, pre[1] = 0, tree[D + 1] = 1, update(D + 1);
        while(x = tree[1])
        {
            strcpy(code, b[x]);
            tree[D + x] = 0, update(D + x);
            for(i = 0; i < 10; i ++)
                for(j = '0'; j <= '9'; j ++)
                    if(j != code[i])
                    {
                        code[i] = j;
                        y = search(code);
                        if(y != -1 && dis[x] + cost[i] < dis[y])
                            dis[y] = dis[x] + cost[i], pre[y] = x, tree[D + y] = y, update(D + y);
                        code[i] = b[x][i];
                    }
            for(i = 0; i < 10; i ++)
                for(j = i + 1; j < 10; j ++)
                    if(code[i] != code[j])
                    {
                        Swap(code[i], code[j]);
                            y = search(code);
                        if(y != -1 && dis[x] + cost[i] < dis[y])
                            dis[y] = dis[x] + cost[i], pre[y] = x, tree[D + y] = y, update(D + y);
                        Swap(code[i], code[j]);    
                    }
        }
        if(dis[N] == INF)
            printf("-1\n");    
        else
        {
            printf("%d\n", dis[N]);
            dfs(N, 1);
            printf("\n");
        }
    }
    int main()
    {
        while(scanf("%d", &N) == 1)
        {
            init();
            solve();    
        }
        return 0;    
    }
  • 相关阅读:
    【linux高级程序设计】(第十章)Linux异步信号处理机制
    【linux高级程序设计】(第九章)进程间通信-管道 3
    【linux高级程序设计】(第九章)进程间通信-管道 2
    用ELK 实时处理搜索日志
    轻松学会多线程(二)——多线程相关概念介绍
    没有IP地址的主机怎样保持IP层联通
    1079. Total Sales of Supply Chain (25)【树+搜索】——PAT (Advanced Level) Practise
    POJ 3984 迷宫问题
    boost::asio 之udp协议的使用
    maven的学习系列(二)—maven的文件夹结构
  • 原文地址:https://www.cnblogs.com/staginner/p/2586569.html
Copyright © 2011-2022 走看看