• Zepto Code Rush 2014——Dungeons and Candies


    题目链接

    • 题意:
      k个点,每一个点都是一个n * m的char型矩阵。对与每一个点,权值为n * m或者找到一个之前的点,取两个矩阵相应位置不同的字符个数乘以w。找到一个序列,使得全部点的权值和最小
    • 分析:
      首先,这个图是一个无向图。求权值和最小,每一个权值相应的是一条边,且每一个点仅仅能有一个权值即一条边,一个k个边,和生成树非常像,可是须要证明不能有环形。最好还是如果如今有三个点,每一个点的最小边成环,这时候是不能找到一个序列使得每一个点都取到它的最小边值的,所以,k个点k个边不能有环且边值和最小,就是最小生成树。

    prim算法:
    const int maxn = 1100;
    
    char ipt[maxn][11][11];
    int dist[maxn][maxn];
    int d[maxn], p[maxn];
    bool vis[maxn];
    int n, m, k, w;
    
    int main()
    {
    //    freopen("in.txt", "r", stdin);
        while (~RIV(n, m, k, w))
        {
            CLR(dist, 0);
            REP(i, k)
            {
                vis[i] = false;
                d[i] = n * m;
                p[i] = -1;
            }
    
            REP(i, k) REP(j, n)
                RS(ipt[i][j]);
            REP(i, k) REP(j, k) REP(ii, n) REP(jj, m)
                dist[i][j] += (ipt[i][ii][jj] != ipt[j][ii][jj]) * w;
            d[0] = 0;
            int sum = n * m;
            VI ans;
            REP(i, k)
            {
                int M = INF, ind;
                REP(j, k)
                    if (!vis[j] && d[j] < M)
                    {
                        ind = j;
                        M = d[j];
                    }
                vis[ind] = true;
                sum += M;
                ans.push_back(ind);
                REP(j, k)
                {
                    if (!vis[j] && dist[ind][j] < d[j])
                    {
                        d[j] = dist[ind][j];
                        p[j] = ind;
                    }
                }
            }
            WI(sum);
            REP(i, ans.size())
            {
                cout << ans[i] + 1 << ' ' << p[ans[i]] + 1 << endl;
            }
        }
        return 0;
    }


    kruskal:
    const int maxn = 1100;
    
    struct Edge
    {
        int from, to, dist;
        int operator< (const Edge& rhs) const
        {
            return dist < rhs.dist;
        }
        Edge (int from = 0, int to = 0, int dist = 0)
        {
            this->from = from;
            this->to = to;
            this->dist = dist;
        }
    };
    
    vector<Edge> G[maxn];
    int in[maxn];
    vector<Edge> edges;
    int fa[maxn];
    char ipt[maxn][105];
    int diff[maxn][maxn];
    int n, m, k, w;
    int find(int n)
    {
        return (n == fa[n]) ? n : (fa[n] = find(fa[n]));
    }
    void init(int n)
    {
        REP(i, n)
        {
            fa[i] = i;
            G[i].clear();
            in[i] = 0;
        }
        edges.clear();
    }
    void AddEdge(int u, int v, int dist)
    {
        edges.push_back(Edge(u, v, dist));
    }
    void dfs(int u, int fa)
    {
        REP(i, G[u].size())
        {
            Edge& e = G[u][i];
            if (e.to != fa)
            {
                if (e.dist == m * n)
                    cout << e.to + 1 << ' ' << 0 << endl;
                else
                    cout << e.to + 1 << ' ' << u + 1 << endl;
                dfs(e.to, u);
            }
        }
    }
    void solve()
    {
        int ret = 0;
        sort(all(edges));
        REP(i, edges.size())
        {
            Edge& e = edges[i];
            int ru = find(e.from), rv = find(e.to);
            if (ru != rv)
            {
                fa[ru] = rv;
                ret += e.dist;
                G[e.from].push_back(Edge(e.from, e.to, e.dist));
                G[e.to].push_back(Edge(e.to, e.from, e.dist));
                in[e.from]++;
                in[e.to]++;
            }
        }
        WI(ret + n * m);
        REP(i, k)
        {
            if (in[i] <= 1)
            {
                cout << i + 1 << ' ' << 0 << endl;
                dfs(i, -1);
                break;
            }
        }
    }
    
    int judge(int a, int b)
    {
        int cnt = 0;
        REP(i, n * m)
            cnt += (ipt[a][i] != ipt[b][i]);
        return cnt;
    }
    
    int main()
    {
    //    freopen("in.txt", "r", stdin);
        while (~RIV(n, m, k, w))
        {
            CLR(diff, 0);
            REP(i, k)
            {
                int len = 0;
                REP(j, n)
                {
                    RS(ipt[i] + len);
                    len = strlen(ipt[i]);
                }
            }
            REP(i, k) REP(j, k) REP(t, n * m)
                diff[i][j] += (ipt[i][t] != ipt[j][t]);
            init(k);
            REP(i, k) REP(j, k)
            {
                if (i == j)
                    continue;
                AddEdge(i, j, min(diff[i][j] * w, n * m));
            }
            solve();
        }
        return 0;
    }

  • 相关阅读:
    php pcntl 多进程学习
    php socket 学习
    linux 常用alias
    php 设置一个函数的最大运行时间
    QTableView 一列添加两个按钮
    翻译qmake文档 目录
    翻译qmake文档(四) Building Common Project Types
    算法时间复杂度
    翻译qmake文档(三) Creating Project Files
    Caliburn.Micro学习笔记目录
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/4247984.html
Copyright © 2020-2023  润新知